From 5971d63df629ce52a3c44770008ab1d9efcd47fd Mon Sep 17 00:00:00 2001 From: Lauri Kasanen Date: Sat, 30 Nov 2013 15:51:10 +0200 Subject: [PATCH] Dawn of a new world --- .gitignore | 38 + COPYING | 675 +++++ Makefile.am | 35 + README | 43 + Xext/Makefile.am | 65 + Xext/bigreq.c | 101 + Xext/dpms.c | 453 ++++ Xext/dpmsproc.h | 15 + Xext/saver.c | 1427 ++++++++++ Xext/shape.c | 1241 +++++++++ Xext/shm.c | 991 +++++++ Xext/shmint.h | 43 + Xext/sleepuntil.c | 240 ++ Xext/sleepuntil.h | 42 + Xext/sync.c | 2456 +++++++++++++++++ Xext/xcmisc.c | 244 ++ Xext/xf86bigfont.c | 779 ++++++ Xext/xf86bigfontsrv.h | 33 + Xext/xres.c | 392 +++ Xext/xtest.c | 436 +++ autogen.sh | 10 + configure.ac | 687 +++++ damageext/Makefile.am | 8 + damageext/damageext.c | 515 ++++ damageext/damageext.h | 33 + damageext/damageextint.h | 91 + dbe/Makefile.am | 10 + dbe/dbe.c | 1829 +++++++++++++ dbe/dbestruct.h | 226 ++ dbe/midbe.c | 791 ++++++ dbe/midbe.h | 43 + dbe/midbestr.h | 93 + dix/Makefile.am | 33 + dix/atom.c | 212 ++ dix/colormap.c | 2555 ++++++++++++++++++ dix/cursor.c | 442 +++ dix/devices.c | 1363 ++++++++++ dix/dispatch.c | 3865 +++++++++++++++++++++++++++ dix/dispatch.h | 146 + dix/dixfonts.c | 2053 ++++++++++++++ dix/dixutils.c | 837 ++++++ dix/events.c | 3437 ++++++++++++++++++++++++ dix/extension.c | 404 +++ dix/ffs.c | 39 + dix/gc.c | 1275 +++++++++ dix/globals.c | 176 ++ dix/glyphcurs.c | 194 ++ dix/grabs.c | 404 +++ dix/initatoms.c | 153 ++ dix/main.c | 661 +++++ dix/pixmap.c | 143 + dix/privates.c | 340 +++ dix/property.c | 610 +++++ dix/resource.c | 844 ++++++ dix/strcasecmp.c | 48 + dix/swaprep.c | 1185 +++++++++ dix/swapreq.c | 1084 ++++++++ dix/tables.c | 985 +++++++ dix/window.c | 3362 +++++++++++++++++++++++ fb/Makefile.am | 45 + fb/fb.h | 1565 +++++++++++ fb/fb24_32.c | 586 ++++ fb/fb24_32.h | 44 + fb/fballpriv.c | 82 + fb/fbarc.c | 117 + fb/fbbits.c | 175 ++ fb/fbbits.h | 938 +++++++ fb/fbblt.c | 818 ++++++ fb/fbbltone.c | 840 ++++++ fb/fbcmap.c | 114 + fb/fbcompose.c | 4284 ++++++++++++++++++++++++++++++ fb/fbcopy.c | 584 ++++ fb/fbedge.c | 286 ++ fb/fbedgeimp.h | 138 + fb/fbfill.c | 204 ++ fb/fbfillrect.c | 103 + fb/fbfillsp.c | 93 + fb/fbgc.c | 321 +++ fb/fbgetsp.c | 73 + fb/fbglyph.c | 451 ++++ fb/fbimage.c | 295 ++ fb/fbline.c | 160 ++ fb/fboverlay.c | 424 +++ fb/fboverlay.h | 116 + fb/fbpict.c | 1240 +++++++++ fb/fbpict.h | 610 +++++ fb/fbpixmap.c | 365 +++ fb/fbpoint.c | 165 ++ fb/fbpush.c | 202 ++ fb/fbrop.h | 137 + fb/fbscreen.c | 214 ++ fb/fbseg.c | 677 +++++ fb/fbsetsp.c | 93 + fb/fbsolid.c | 187 ++ fb/fbstipple.c | 277 ++ fb/fbtile.c | 161 ++ fb/fbtrap.c | 239 ++ fb/fbutil.c | 293 ++ fb/fbwindow.c | 314 +++ include/Makefile.am | 12 + include/closestr.h | 156 ++ include/closure.h | 57 + include/colormap.h | 182 ++ include/colormapst.h | 133 + include/cursor.h | 138 + include/cursorstr.h | 91 + include/dix-config.h.in | 257 ++ include/dix.h | 729 +++++ include/dixevents.h | 97 + include/dixfont.h | 150 ++ include/dixfontstr.h | 93 + include/dixgrabs.h | 58 + include/dixstruct.h | 195 ++ include/exevents.h | 182 ++ include/extension.h | 71 + include/extinit.h | 166 ++ include/extnsionst.h | 143 + include/gc.h | 176 ++ include/gcstruct.h | 322 +++ include/globals.h | 82 + include/input.h | 333 +++ include/inputstr.h | 297 +++ include/kdrive-config.h.in | 21 + include/misc.h | 298 +++ include/miscstruct.h | 78 + include/opaque.h | 75 + include/os.h | 407 +++ include/pixmap.h | 108 + include/pixmapstr.h | 91 + include/property.h | 72 + include/propertyst.h | 66 + include/region.h | 53 + include/regionstr.h | 266 ++ include/resource.h | 256 ++ include/screenint.h | 106 + include/scrnintstr.h | 532 ++++ include/selection.h | 68 + include/servermd.h | 397 +++ include/site.h | 130 + include/swaprep.h | 310 +++ include/swapreq.h | 119 + include/validate.h | 40 + include/window.h | 264 ++ include/windowstr.h | 191 ++ kdrive/Makefile.am | 19 + kdrive/fbdev/Makefile.am | 28 + kdrive/fbdev/fbdev.c | 784 ++++++ kdrive/fbdev/fbdev.h | 80 + kdrive/fbdev/fbinit.c | 100 + kdrive/linux/Makefile.am | 20 + kdrive/linux/keyboard.c | 469 ++++ kdrive/linux/linux.c | 342 +++ kdrive/linux/mouse.c | 943 +++++++ kdrive/src/Makefile.am | 22 + kdrive/src/kcmap.c | 241 ++ kdrive/src/kdrive.c | 1230 +++++++++ kdrive/src/kdrive.h | 419 +++ kdrive/src/kinfo.c | 137 + kdrive/src/kinput.c | 1578 +++++++++++ kdrive/src/kkeymap.h | 52 + kdrive/src/kmap.c | 151 ++ kdrive/src/kmode.c | 270 ++ kdrive/src/kshadow.c | 77 + kdrive/vesa/Makefile.am | 34 + kdrive/vesa/vbe.c | 692 +++++ kdrive/vesa/vbe.h | 145 + kdrive/vesa/vesa.c | 1696 ++++++++++++ kdrive/vesa/vesa.h | 139 + kdrive/vesa/vesainit.c | 106 + kdrive/vesa/vga.c | 224 ++ kdrive/vesa/vga.h | 47 + kdrive/vesa/vm86.c | 754 ++++++ kdrive/vesa/vm86.h | 144 + loc.sh | 3 + m4/ax_check_compile_flag.m4 | 72 + m4/ax_check_link_flag.m4 | 71 + m4/dir.m4 | 14 + mi/Makefile.am | 61 + mi/mi.h | 588 ++++ mi/miarc.c | 3718 ++++++++++++++++++++++++++ mi/mibank.c | 2455 +++++++++++++++++ mi/mibank.h | 118 + mi/mibitblt.c | 843 ++++++ mi/micmap.c | 653 +++++ mi/micmap.h | 64 + mi/micoord.h | 70 + mi/micursor.c | 75 + mi/midash.c | 313 +++ mi/midispcur.c | 813 ++++++ mi/mieq.c | 193 ++ mi/miexpose.c | 545 ++++ mi/mifillarc.c | 815 ++++++ mi/mifillarc.h | 214 ++ mi/mifillrct.c | 142 + mi/mifpoly.h | 109 + mi/mifpolycon.c | 282 ++ mi/migc.c | 299 +++ mi/migc.h | 72 + mi/miglblt.c | 253 ++ mi/miinitext.c | 234 ++ mi/miline.h | 172 ++ mi/mipointer.c | 527 ++++ mi/mipointer.h | 151 ++ mi/mipointrst.h | 62 + mi/mipoly.c | 127 + mi/mipoly.h | 215 ++ mi/mipolycon.c | 246 ++ mi/mipolygen.c | 230 ++ mi/mipolypnt.c | 123 + mi/mipolyrect.c | 191 ++ mi/mipolyseg.c | 83 + mi/mipolytext.c | 152 ++ mi/mipolyutil.c | 399 +++ mi/mipushpxl.c | 274 ++ mi/miregion.c | 2181 +++++++++++++++ mi/miscanfill.h | 147 + mi/miscrinit.c | 330 +++ mi/mispans.c | 542 ++++ mi/mispans.h | 98 + mi/misprite.c | 778 ++++++ mi/misprite.h | 94 + mi/mispritest.h | 127 + mi/mistruct.h | 63 + mi/mivalidate.h | 53 + mi/mivaltree.c | 770 ++++++ mi/miwideline.c | 2231 ++++++++++++++++ mi/miwideline.h | 222 ++ mi/miwindow.c | 850 ++++++ mi/mizerarc.c | 853 ++++++ mi/mizerarc.h | 132 + mi/mizerclip.c | 635 +++++ mi/mizerline.c | 378 +++ miext/Makefile.am | 2 + miext/damage/Makefile.am | 10 + miext/damage/damage.c | 1922 ++++++++++++++ miext/damage/damage.h | 81 + miext/damage/damagestr.h | 114 + miext/shadow/Makefile.am | 28 + miext/shadow/shadow.c | 257 ++ miext/shadow/shadow.h | 163 ++ miext/shadow/shalloc.c | 51 + miext/shadow/shpacked.c | 127 + miext/shadow/shplanar.c | 195 ++ miext/shadow/shplanar8.c | 184 ++ miext/shadow/shrot16pack.c | 31 + miext/shadow/shrot16pack_180.c | 32 + miext/shadow/shrot16pack_270.c | 32 + miext/shadow/shrot16pack_270YX.c | 32 + miext/shadow/shrot16pack_90.c | 32 + miext/shadow/shrot16pack_90YX.c | 32 + miext/shadow/shrot32pack.c | 31 + miext/shadow/shrot32pack_180.c | 32 + miext/shadow/shrot32pack_270.c | 32 + miext/shadow/shrot32pack_90.c | 32 + miext/shadow/shrot8pack.c | 31 + miext/shadow/shrot8pack_180.c | 32 + miext/shadow/shrot8pack_270.c | 32 + miext/shadow/shrot8pack_90.c | 32 + miext/shadow/shrotate.c | 333 +++ miext/shadow/shrotpack.h | 207 ++ miext/shadow/shrotpackYX.h | 167 ++ os/Makefile.am | 33 + os/WaitFor.c | 670 +++++ os/access.c | 1951 ++++++++++++++ os/auth.c | 236 ++ os/connection.c | 996 +++++++ os/io.c | 1026 +++++++ os/log.c | 194 ++ os/mitauth.c | 162 ++ os/oscolor.c | 1598 +++++++++++ os/osdep.h | 274 ++ os/osinit.c | 199 ++ os/strlcat.c | 56 + os/strlcpy.c | 51 + os/utils.c | 1640 ++++++++++++ os/xauembed.c | 120 + os/xdmauth.c | 501 ++++ os/xdmcp.c | 1618 +++++++++++ os/xstrans.c | 30 + randr/Makefile.am | 18 + randr/mirandr.c | 144 + randr/randr.c | 495 ++++ randr/randrstr.h | 801 ++++++ randr/rrcrtc.c | 865 ++++++ randr/rrdispatch.c | 207 ++ randr/rrinfo.c | 335 +++ randr/rrmode.c | 254 ++ randr/rroutput.c | 452 ++++ randr/rrpointer.c | 151 ++ randr/rrproperty.c | 637 +++++ randr/rrscreen.c | 942 +++++++ randr/rrsdispatch.c | 302 +++ randr/rrxinerama.c | 437 +++ render/Makefile.am | 22 + render/animcur.c | 388 +++ render/filter.c | 336 +++ render/glyph.c | 729 +++++ render/glyphstr.h | 148 ++ render/miglyph.c | 250 ++ render/miindex.c | 359 +++ render/mipict.c | 609 +++++ render/mipict.h | 191 ++ render/mirect.c | 179 ++ render/mitrap.c | 189 ++ render/mitri.c | 190 ++ render/picture.c | 1846 +++++++++++++ render/picture.h | 246 ++ render/picturestr.h | 608 +++++ render/render.c | 2697 +++++++++++++++++++ render/renderedge.c | 190 ++ render/renderedge.h | 113 + xfixes/Makefile.am | 12 + xfixes/cursor.c | 1027 +++++++ xfixes/region.c | 857 ++++++ xfixes/saveset.c | 77 + xfixes/select.c | 257 ++ xfixes/xfixes.c | 259 ++ xfixes/xfixes.h | 52 + xfixes/xfixesint.h | 281 ++ 319 files changed, 138294 insertions(+) create mode 100644 .gitignore create mode 100644 COPYING create mode 100644 Makefile.am create mode 100644 README create mode 100644 Xext/Makefile.am create mode 100644 Xext/bigreq.c create mode 100644 Xext/dpms.c create mode 100644 Xext/dpmsproc.h create mode 100644 Xext/saver.c create mode 100644 Xext/shape.c create mode 100644 Xext/shm.c create mode 100644 Xext/shmint.h create mode 100644 Xext/sleepuntil.c create mode 100644 Xext/sleepuntil.h create mode 100644 Xext/sync.c create mode 100644 Xext/xcmisc.c create mode 100644 Xext/xf86bigfont.c create mode 100644 Xext/xf86bigfontsrv.h create mode 100644 Xext/xres.c create mode 100644 Xext/xtest.c create mode 100755 autogen.sh create mode 100644 configure.ac create mode 100644 damageext/Makefile.am create mode 100644 damageext/damageext.c create mode 100644 damageext/damageext.h create mode 100644 damageext/damageextint.h create mode 100644 dbe/Makefile.am create mode 100644 dbe/dbe.c create mode 100644 dbe/dbestruct.h create mode 100644 dbe/midbe.c create mode 100644 dbe/midbe.h create mode 100644 dbe/midbestr.h create mode 100644 dix/Makefile.am create mode 100644 dix/atom.c create mode 100644 dix/colormap.c create mode 100644 dix/cursor.c create mode 100644 dix/devices.c create mode 100644 dix/dispatch.c create mode 100644 dix/dispatch.h create mode 100644 dix/dixfonts.c create mode 100644 dix/dixutils.c create mode 100644 dix/events.c create mode 100644 dix/extension.c create mode 100644 dix/ffs.c create mode 100644 dix/gc.c create mode 100644 dix/globals.c create mode 100644 dix/glyphcurs.c create mode 100644 dix/grabs.c create mode 100644 dix/initatoms.c create mode 100644 dix/main.c create mode 100644 dix/pixmap.c create mode 100644 dix/privates.c create mode 100644 dix/property.c create mode 100644 dix/resource.c create mode 100644 dix/strcasecmp.c create mode 100644 dix/swaprep.c create mode 100644 dix/swapreq.c create mode 100644 dix/tables.c create mode 100644 dix/window.c create mode 100644 fb/Makefile.am create mode 100644 fb/fb.h create mode 100644 fb/fb24_32.c create mode 100644 fb/fb24_32.h create mode 100644 fb/fballpriv.c create mode 100644 fb/fbarc.c create mode 100644 fb/fbbits.c create mode 100644 fb/fbbits.h create mode 100644 fb/fbblt.c create mode 100644 fb/fbbltone.c create mode 100644 fb/fbcmap.c create mode 100644 fb/fbcompose.c create mode 100644 fb/fbcopy.c create mode 100644 fb/fbedge.c create mode 100644 fb/fbedgeimp.h create mode 100644 fb/fbfill.c create mode 100644 fb/fbfillrect.c create mode 100644 fb/fbfillsp.c create mode 100644 fb/fbgc.c create mode 100644 fb/fbgetsp.c create mode 100644 fb/fbglyph.c create mode 100644 fb/fbimage.c create mode 100644 fb/fbline.c create mode 100644 fb/fboverlay.c create mode 100644 fb/fboverlay.h create mode 100644 fb/fbpict.c create mode 100644 fb/fbpict.h create mode 100644 fb/fbpixmap.c create mode 100644 fb/fbpoint.c create mode 100644 fb/fbpush.c create mode 100644 fb/fbrop.h create mode 100644 fb/fbscreen.c create mode 100644 fb/fbseg.c create mode 100644 fb/fbsetsp.c create mode 100644 fb/fbsolid.c create mode 100644 fb/fbstipple.c create mode 100644 fb/fbtile.c create mode 100644 fb/fbtrap.c create mode 100644 fb/fbutil.c create mode 100644 fb/fbwindow.c create mode 100644 include/Makefile.am create mode 100644 include/closestr.h create mode 100644 include/closure.h create mode 100644 include/colormap.h create mode 100644 include/colormapst.h create mode 100644 include/cursor.h create mode 100644 include/cursorstr.h create mode 100644 include/dix-config.h.in create mode 100644 include/dix.h create mode 100644 include/dixevents.h create mode 100644 include/dixfont.h create mode 100644 include/dixfontstr.h create mode 100644 include/dixgrabs.h create mode 100644 include/dixstruct.h create mode 100644 include/exevents.h create mode 100644 include/extension.h create mode 100644 include/extinit.h create mode 100644 include/extnsionst.h create mode 100644 include/gc.h create mode 100644 include/gcstruct.h create mode 100644 include/globals.h create mode 100644 include/input.h create mode 100644 include/inputstr.h create mode 100644 include/kdrive-config.h.in create mode 100644 include/misc.h create mode 100644 include/miscstruct.h create mode 100644 include/opaque.h create mode 100644 include/os.h create mode 100644 include/pixmap.h create mode 100644 include/pixmapstr.h create mode 100644 include/property.h create mode 100644 include/propertyst.h create mode 100644 include/region.h create mode 100644 include/regionstr.h create mode 100644 include/resource.h create mode 100644 include/screenint.h create mode 100644 include/scrnintstr.h create mode 100644 include/selection.h create mode 100644 include/servermd.h create mode 100644 include/site.h create mode 100644 include/swaprep.h create mode 100644 include/swapreq.h create mode 100644 include/validate.h create mode 100644 include/window.h create mode 100644 include/windowstr.h create mode 100644 kdrive/Makefile.am create mode 100644 kdrive/fbdev/Makefile.am create mode 100644 kdrive/fbdev/fbdev.c create mode 100644 kdrive/fbdev/fbdev.h create mode 100644 kdrive/fbdev/fbinit.c create mode 100644 kdrive/linux/Makefile.am create mode 100644 kdrive/linux/keyboard.c create mode 100644 kdrive/linux/linux.c create mode 100644 kdrive/linux/mouse.c create mode 100644 kdrive/src/Makefile.am create mode 100644 kdrive/src/kcmap.c create mode 100644 kdrive/src/kdrive.c create mode 100644 kdrive/src/kdrive.h create mode 100644 kdrive/src/kinfo.c create mode 100644 kdrive/src/kinput.c create mode 100644 kdrive/src/kkeymap.h create mode 100644 kdrive/src/kmap.c create mode 100644 kdrive/src/kmode.c create mode 100644 kdrive/src/kshadow.c create mode 100644 kdrive/vesa/Makefile.am create mode 100644 kdrive/vesa/vbe.c create mode 100644 kdrive/vesa/vbe.h create mode 100644 kdrive/vesa/vesa.c create mode 100644 kdrive/vesa/vesa.h create mode 100644 kdrive/vesa/vesainit.c create mode 100644 kdrive/vesa/vga.c create mode 100644 kdrive/vesa/vga.h create mode 100644 kdrive/vesa/vm86.c create mode 100644 kdrive/vesa/vm86.h create mode 100755 loc.sh create mode 100644 m4/ax_check_compile_flag.m4 create mode 100644 m4/ax_check_link_flag.m4 create mode 100644 m4/dir.m4 create mode 100644 mi/Makefile.am create mode 100644 mi/mi.h create mode 100644 mi/miarc.c create mode 100644 mi/mibank.c create mode 100644 mi/mibank.h create mode 100644 mi/mibitblt.c create mode 100644 mi/micmap.c create mode 100644 mi/micmap.h create mode 100644 mi/micoord.h create mode 100644 mi/micursor.c create mode 100644 mi/midash.c create mode 100644 mi/midispcur.c create mode 100644 mi/mieq.c create mode 100644 mi/miexpose.c create mode 100644 mi/mifillarc.c create mode 100644 mi/mifillarc.h create mode 100644 mi/mifillrct.c create mode 100644 mi/mifpoly.h create mode 100644 mi/mifpolycon.c create mode 100644 mi/migc.c create mode 100644 mi/migc.h create mode 100644 mi/miglblt.c create mode 100644 mi/miinitext.c create mode 100644 mi/miline.h create mode 100644 mi/mipointer.c create mode 100644 mi/mipointer.h create mode 100644 mi/mipointrst.h create mode 100644 mi/mipoly.c create mode 100644 mi/mipoly.h create mode 100644 mi/mipolycon.c create mode 100644 mi/mipolygen.c create mode 100644 mi/mipolypnt.c create mode 100644 mi/mipolyrect.c create mode 100644 mi/mipolyseg.c create mode 100644 mi/mipolytext.c create mode 100644 mi/mipolyutil.c create mode 100644 mi/mipushpxl.c create mode 100644 mi/miregion.c create mode 100644 mi/miscanfill.h create mode 100644 mi/miscrinit.c create mode 100644 mi/mispans.c create mode 100644 mi/mispans.h create mode 100644 mi/misprite.c create mode 100644 mi/misprite.h create mode 100644 mi/mispritest.h create mode 100644 mi/mistruct.h create mode 100644 mi/mivalidate.h create mode 100644 mi/mivaltree.c create mode 100644 mi/miwideline.c create mode 100644 mi/miwideline.h create mode 100644 mi/miwindow.c create mode 100644 mi/mizerarc.c create mode 100644 mi/mizerarc.h create mode 100644 mi/mizerclip.c create mode 100644 mi/mizerline.c create mode 100644 miext/Makefile.am create mode 100644 miext/damage/Makefile.am create mode 100644 miext/damage/damage.c create mode 100644 miext/damage/damage.h create mode 100644 miext/damage/damagestr.h create mode 100644 miext/shadow/Makefile.am create mode 100644 miext/shadow/shadow.c create mode 100644 miext/shadow/shadow.h create mode 100644 miext/shadow/shalloc.c create mode 100644 miext/shadow/shpacked.c create mode 100644 miext/shadow/shplanar.c create mode 100644 miext/shadow/shplanar8.c create mode 100644 miext/shadow/shrot16pack.c create mode 100644 miext/shadow/shrot16pack_180.c create mode 100644 miext/shadow/shrot16pack_270.c create mode 100644 miext/shadow/shrot16pack_270YX.c create mode 100644 miext/shadow/shrot16pack_90.c create mode 100644 miext/shadow/shrot16pack_90YX.c create mode 100644 miext/shadow/shrot32pack.c create mode 100644 miext/shadow/shrot32pack_180.c create mode 100644 miext/shadow/shrot32pack_270.c create mode 100644 miext/shadow/shrot32pack_90.c create mode 100644 miext/shadow/shrot8pack.c create mode 100644 miext/shadow/shrot8pack_180.c create mode 100644 miext/shadow/shrot8pack_270.c create mode 100644 miext/shadow/shrot8pack_90.c create mode 100644 miext/shadow/shrotate.c create mode 100644 miext/shadow/shrotpack.h create mode 100644 miext/shadow/shrotpackYX.h create mode 100644 os/Makefile.am create mode 100644 os/WaitFor.c create mode 100644 os/access.c create mode 100644 os/auth.c create mode 100644 os/connection.c create mode 100644 os/io.c create mode 100644 os/log.c create mode 100644 os/mitauth.c create mode 100644 os/oscolor.c create mode 100644 os/osdep.h create mode 100644 os/osinit.c create mode 100644 os/strlcat.c create mode 100644 os/strlcpy.c create mode 100644 os/utils.c create mode 100644 os/xauembed.c create mode 100644 os/xdmauth.c create mode 100644 os/xdmcp.c create mode 100644 os/xstrans.c create mode 100644 randr/Makefile.am create mode 100644 randr/mirandr.c create mode 100644 randr/randr.c create mode 100644 randr/randrstr.h create mode 100644 randr/rrcrtc.c create mode 100644 randr/rrdispatch.c create mode 100644 randr/rrinfo.c create mode 100644 randr/rrmode.c create mode 100644 randr/rroutput.c create mode 100644 randr/rrpointer.c create mode 100644 randr/rrproperty.c create mode 100644 randr/rrscreen.c create mode 100644 randr/rrsdispatch.c create mode 100644 randr/rrxinerama.c create mode 100644 render/Makefile.am create mode 100644 render/animcur.c create mode 100644 render/filter.c create mode 100644 render/glyph.c create mode 100644 render/glyphstr.h create mode 100644 render/miglyph.c create mode 100644 render/miindex.c create mode 100644 render/mipict.c create mode 100644 render/mipict.h create mode 100644 render/mirect.c create mode 100644 render/mitrap.c create mode 100644 render/mitri.c create mode 100644 render/picture.c create mode 100644 render/picture.h create mode 100644 render/picturestr.h create mode 100644 render/render.c create mode 100644 render/renderedge.c create mode 100644 render/renderedge.h create mode 100644 xfixes/Makefile.am create mode 100644 xfixes/cursor.c create mode 100644 xfixes/region.c create mode 100644 xfixes/saveset.c create mode 100644 xfixes/select.c create mode 100644 xfixes/xfixes.c create mode 100644 xfixes/xfixes.h create mode 100644 xfixes/xfixesint.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e572126 --- /dev/null +++ b/.gitignore @@ -0,0 +1,38 @@ +Makefile +Makefile.in +.deps +.libs +.msg +*.lo +*.la +*.a +*.o +*~ +aclocal.m4 +autom4te.cache +m4/lt*m4 +m4/libtool.m4 +compile +config.guess +config.log +config.status +config.sub +configure +depcomp +install-sh +libtool +ltmain.sh +missing +xorg-server.pc +stamp-h? +do-not-use-config.h +do-not-use-config.h.in +kdrive/fbdev/Xfbdev +kdrive/vesa/Xvesa +include/dix-config.h +include/kdrive-config.h +include/xkb-config.h +ylwrap +err +*rig +*rej diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..10926e8 --- /dev/null +++ b/COPYING @@ -0,0 +1,675 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. + diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..ad1e3e4 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,35 @@ +ACLOCAL_AMFLAGS=-I m4 + +if DBE +DBE_DIR=dbe +endif + +SUBDIRS = \ + include \ + dix \ + fb \ + mi \ + Xext \ + miext \ + os \ + randr \ + render \ + $(DBE_DIR) \ + xfixes \ + damageext \ + kdrive + +DIST_SUBDIRS = \ + include \ + dix \ + fb \ + mi \ + Xext \ + miext \ + os \ + randr \ + render \ + dbe \ + xfixes \ + damageext \ + kdrive diff --git a/README b/README new file mode 100644 index 0000000..74daf74 --- /dev/null +++ b/README @@ -0,0 +1,43 @@ +Necromancy +========== + +We resurrected Xvesa from the depths of git history, and intend to maintain it with Xfbdev. + +This includes bugfixes, security fixes, and occasional new features if required. + + +Why? +---- + +The TinyX servers fill our needs while being a lot smaller than Xorg can be made. + + +Why 1.2.0 and not 1.3.0? +------------------------ + +As you know, Xvesa was killed in 1.4.0, so the latest released version would be 1.3.0. +However, they broke all input in 1.3.0 (keyboard and mouse), so the last working released +version is 1.2.0. + +There were also some changes later on that we disagree with (mandatory xinput & xkb). + + +Design choices +-------------- + +We aim for the smallest fully featured X server binary. Currently there are the vesa and +fbdev servers, but others may appear in the future (Xmodesetting?). + +- no xkb; it's bloat when console keymaps suffice +- no xinput +- no xinerama +- no gl +- TCP listening disabled by default, shadow FB enabled by default +... + + +Licensing +--------- + +While the original codebase is MIT, any changes here are GPLv3. Supporting closed devices +with this code is not a goal. diff --git a/Xext/Makefile.am b/Xext/Makefile.am new file mode 100644 index 0000000..6dc829e --- /dev/null +++ b/Xext/Makefile.am @@ -0,0 +1,65 @@ +# libXext.la: includes all extensions and should be linked into Xvfb, +# Xnest, Xdmx and Xprt +# libXextbuiltin.la: includes those extensions that are built directly into +# Xorg by default +# libXextmodule.la: includes those extensions that are built into a module +# that Xorg loads +noinst_LTLIBRARIES = libXext.la + +AM_CFLAGS = $(DIX_CFLAGS) + +# Sources always included in libXextbuiltin.la & libXext.la +BUILTIN_SRCS = \ + shape.c \ + sleepuntil.c \ + sleepuntil.h \ + xtest.c + +# Sources always included in libXextmodule.la & libXext.la +MODULE_SRCS = \ + bigreq.c \ + shape.c \ + sync.c \ + xcmisc.c + +# Optional sources included if extension enabled by configure.ac rules + +# MIT Shared Memory extension +MITSHM_SRCS = shm.c shmint.h +BUILTIN_SRCS += $(MITSHM_SRCS) + +# XResource extension: lets clients get data about per-client resource usage +RES_SRCS = xres.c +if RES +MODULE_SRCS += $(RES_SRCS) +endif + +# MIT ScreenSaver extension +SCREENSAVER_SRCS = saver.c +if SCREENSAVER +MODULE_SRCS += $(SCREENSAVER_SRCS) +endif + +# XF86 Big Font extension +BIGFONT_SRCS = xf86bigfont.c xf86bigfontsrv.h +if XF86BIGFONT +BUILTIN_SRCS += $(BIGFONT_SRCS) +endif + +# DPMS extension +DPMS_SRCS = dpms.c dpmsproc.h +if DPMSExtension +MODULE_SRCS += $(DPMS_SRCS) +endif + +# Now take all of the above, mix well, bake for 10 minutes and get libXext*.la + +libXext_la_SOURCES = $(BUILTIN_SRCS) $(MODULE_SRCS) + +EXTRA_DIST = \ + $(MITSHM_SRCS) \ + $(RES_SRCS) \ + $(SCREENSAVER_SRCS) \ + $(BIGFONT_SRCS) \ + $(DPMS_SRCS) + diff --git a/Xext/bigreq.c b/Xext/bigreq.c new file mode 100644 index 0000000..6c93052 --- /dev/null +++ b/Xext/bigreq.c @@ -0,0 +1,101 @@ +/* + +Copyright 1992, 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 +#endif + +#include +#include +#include "misc.h" +#include "os.h" +#include "dixstruct.h" +#include "extnsionst.h" +#include +#include "opaque.h" +#include "extinit.h" + +#if 0 +static unsigned char XBigReqCode; +#endif + +static void BigReqResetProc(ExtensionEntry * /* extEntry */ + ); + +static DISPATCH_PROC(ProcBigReqDispatch); + +void +BigReqExtensionInit(INITARGS) +{ +#if 0 + ExtensionEntry *extEntry; + + if ((extEntry = AddExtension(XBigReqExtensionName, 0, 0, + ProcBigReqDispatch, ProcBigReqDispatch, + BigReqResetProc, StandardMinorOpcode)) != 0) + XBigReqCode = (unsigned char) extEntry->base; +#else + (void) AddExtension(XBigReqExtensionName, 0, 0, + ProcBigReqDispatch, ProcBigReqDispatch, + BigReqResetProc, StandardMinorOpcode); +#endif + + DeclareExtensionSecurity(XBigReqExtensionName, TRUE); +} + + /*ARGSUSED*/ static void +BigReqResetProc(extEntry) +ExtensionEntry *extEntry; +{ +} + +static int +ProcBigReqDispatch(client) +ClientPtr client; +{ + REQUEST(xBigReqEnableReq); + xBigReqEnableReply rep = {0}; + + if (client->swapped) { + swaps(&stuff->length); + } + if (stuff->brReqType != X_BigReqEnable) + return BadRequest; + REQUEST_SIZE_MATCH(xBigReqEnableReq); + client->big_requests = TRUE; + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.max_request_size = maxBigRequestSize; + if (client->swapped) { + swaps(&rep.sequenceNumber); + swapl(&rep.max_request_size); + } + WriteToClient(client, sizeof(xBigReqEnableReply), (char *) &rep); + return (client->noClientException); +} diff --git a/Xext/dpms.c b/Xext/dpms.c new file mode 100644 index 0000000..b75f482 --- /dev/null +++ b/Xext/dpms.c @@ -0,0 +1,453 @@ +/***************************************************************** + +Copyright (c) 1996 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. + +******************************************************************/ + +/* + * HISTORY + * + * @(#)RCSfile: dpms.c,v Revision: 1.1.4.5 (DEC) Date: 1996/03/04 15:27:00 + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#include +#include "misc.h" +#include "os.h" +#include "dixstruct.h" +#include "extnsionst.h" +#include "opaque.h" +#define DPMS_SERVER +#include +#include +#include "dpmsproc.h" +#include "extinit.h" + +#if 0 +static unsigned char DPMSCode; +#endif +static DISPATCH_PROC(ProcDPMSDispatch); + +static DISPATCH_PROC(SProcDPMSDispatch); + +static DISPATCH_PROC(ProcDPMSGetVersion); + +static DISPATCH_PROC(SProcDPMSGetVersion); + +static DISPATCH_PROC(ProcDPMSGetTimeouts); + +static DISPATCH_PROC(SProcDPMSGetTimeouts); + +static DISPATCH_PROC(ProcDPMSSetTimeouts); + +static DISPATCH_PROC(SProcDPMSSetTimeouts); + +static DISPATCH_PROC(ProcDPMSEnable); + +static DISPATCH_PROC(SProcDPMSEnable); + +static DISPATCH_PROC(ProcDPMSDisable); + +static DISPATCH_PROC(SProcDPMSDisable); + +static DISPATCH_PROC(ProcDPMSForceLevel); + +static DISPATCH_PROC(SProcDPMSForceLevel); + +static DISPATCH_PROC(ProcDPMSInfo); + +static DISPATCH_PROC(SProcDPMSInfo); + +static DISPATCH_PROC(ProcDPMSCapable); + +static DISPATCH_PROC(SProcDPMSCapable); + +static void DPMSResetProc(ExtensionEntry * extEntry); + +void +DPMSExtensionInit(INITARGS) +{ +#if 0 + ExtensionEntry *extEntry; + + if ((extEntry = AddExtension(DPMSExtensionName, 0, 0, + ProcDPMSDispatch, SProcDPMSDispatch, + DPMSResetProc, StandardMinorOpcode))) + DPMSCode = (unsigned char) extEntry->base; +#else + (void) AddExtension(DPMSExtensionName, 0, 0, + ProcDPMSDispatch, SProcDPMSDispatch, + DPMSResetProc, StandardMinorOpcode); +#endif +} + + /*ARGSUSED*/ static void +DPMSResetProc(extEntry) +ExtensionEntry *extEntry; +{ +} + +static int +ProcDPMSGetVersion(client) +ClientPtr client; +{ + /* REQUEST(xDPMSGetVersionReq); */ + xDPMSGetVersionReply rep; + + + REQUEST_SIZE_MATCH(xDPMSGetVersionReq); + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.majorVersion = DPMSMajorVersion; + rep.minorVersion = DPMSMinorVersion; + if (client->swapped) { + swaps(&rep.sequenceNumber); + swaps(&rep.majorVersion); + swaps(&rep.minorVersion); + } + WriteToClient(client, sizeof(xDPMSGetVersionReply), (char *) &rep); + return (client->noClientException); +} + +static int +ProcDPMSCapable(register ClientPtr client) +{ + /* REQUEST(xDPMSCapableReq); */ + xDPMSCapableReply rep; + + + REQUEST_SIZE_MATCH(xDPMSCapableReq); + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.capable = DPMSCapableFlag; + + if (client->swapped) { + swaps(&rep.sequenceNumber); + } + WriteToClient(client, sizeof(xDPMSCapableReply), (char *) &rep); + return (client->noClientException); +} + +static int +ProcDPMSGetTimeouts(client) +ClientPtr client; +{ + /* REQUEST(xDPMSGetTimeoutsReq); */ + xDPMSGetTimeoutsReply rep; + + + REQUEST_SIZE_MATCH(xDPMSGetTimeoutsReq); + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.standby = DPMSStandbyTime / MILLI_PER_SECOND; + rep.suspend = DPMSSuspendTime / MILLI_PER_SECOND; + rep.off = DPMSOffTime / MILLI_PER_SECOND; + + if (client->swapped) { + swaps(&rep.sequenceNumber); + swaps(&rep.standby); + swaps(&rep.suspend); + swaps(&rep.off); + } + WriteToClient(client, sizeof(xDPMSGetTimeoutsReply), (char *) &rep); + return (client->noClientException); +} + +static int +ProcDPMSSetTimeouts(client) +ClientPtr client; +{ + REQUEST(xDPMSSetTimeoutsReq); + + REQUEST_SIZE_MATCH(xDPMSSetTimeoutsReq); + + if ((stuff->off != 0) && (stuff->off < stuff->suspend)) { + client->errorValue = stuff->off; + return BadValue; + } + if ((stuff->suspend != 0) && (stuff->suspend < stuff->standby)) { + client->errorValue = stuff->suspend; + return BadValue; + } + + DPMSStandbyTime = stuff->standby * MILLI_PER_SECOND; + DPMSSuspendTime = stuff->suspend * MILLI_PER_SECOND; + DPMSOffTime = stuff->off * MILLI_PER_SECOND; + SetScreenSaverTimer(); + + return (client->noClientException); +} + +static int +ProcDPMSEnable(client) +ClientPtr client; +{ + /* REQUEST(xDPMSEnableReq); */ + + REQUEST_SIZE_MATCH(xDPMSEnableReq); + + if (DPMSCapableFlag) + DPMSEnabled = TRUE; + + return (client->noClientException); +} + +static int +ProcDPMSDisable(client) +ClientPtr client; +{ + /* REQUEST(xDPMSDisableReq); */ + + REQUEST_SIZE_MATCH(xDPMSDisableReq); + + DPMSSet(DPMSModeOn); + + DPMSEnabled = FALSE; + + return (client->noClientException); +} + +static int +ProcDPMSForceLevel(client) +ClientPtr client; +{ + REQUEST(xDPMSForceLevelReq); + + REQUEST_SIZE_MATCH(xDPMSForceLevelReq); + + if (!DPMSEnabled) + return BadMatch; + + if (stuff->level == DPMSModeOn) { + lastDeviceEventTime.milliseconds = GetTimeInMillis(); + } + else if (stuff->level == DPMSModeStandby) { + lastDeviceEventTime.milliseconds = GetTimeInMillis() - DPMSStandbyTime; + } + else if (stuff->level == DPMSModeSuspend) { + lastDeviceEventTime.milliseconds = GetTimeInMillis() - DPMSSuspendTime; + } + else if (stuff->level == DPMSModeOff) { + lastDeviceEventTime.milliseconds = GetTimeInMillis() - DPMSOffTime; + } + else { + client->errorValue = stuff->level; + return BadValue; + } + + DPMSSet(stuff->level); + + return (client->noClientException); +} + +static int +ProcDPMSInfo(register ClientPtr client) +{ + /* REQUEST(xDPMSInfoReq); */ + xDPMSInfoReply rep; + + + REQUEST_SIZE_MATCH(xDPMSInfoReq); + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.power_level = DPMSPowerLevel; + rep.state = DPMSEnabled; + + if (client->swapped) { + swaps(&rep.sequenceNumber); + swaps(&rep.power_level); + } + WriteToClient(client, sizeof(xDPMSInfoReply), (char *) &rep); + return (client->noClientException); +} + +static int +ProcDPMSDispatch(client) +ClientPtr client; +{ + REQUEST(xReq); + + switch (stuff->data) { + case X_DPMSGetVersion: + return ProcDPMSGetVersion(client); + case X_DPMSCapable: + return ProcDPMSCapable(client); + case X_DPMSGetTimeouts: + return ProcDPMSGetTimeouts(client); + case X_DPMSSetTimeouts: + return ProcDPMSSetTimeouts(client); + case X_DPMSEnable: + return ProcDPMSEnable(client); + case X_DPMSDisable: + return ProcDPMSDisable(client); + case X_DPMSForceLevel: + return ProcDPMSForceLevel(client); + case X_DPMSInfo: + return ProcDPMSInfo(client); + default: + return BadRequest; + } +} + +static int +SProcDPMSGetVersion(client) +ClientPtr client; +{ + + REQUEST(xDPMSGetVersionReq); + + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xDPMSGetVersionReq); + swaps(&stuff->majorVersion); + swaps(&stuff->minorVersion); + return ProcDPMSGetVersion(client); +} + +static int +SProcDPMSCapable(register ClientPtr client) +{ + REQUEST(xDPMSCapableReq); + + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xDPMSCapableReq); + + return ProcDPMSCapable(client); +} + +static int +SProcDPMSGetTimeouts(client) +ClientPtr client; +{ + REQUEST(xDPMSGetTimeoutsReq); + + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xDPMSGetTimeoutsReq); + + return ProcDPMSGetTimeouts(client); +} + +static int +SProcDPMSSetTimeouts(client) +ClientPtr client; +{ + REQUEST(xDPMSSetTimeoutsReq); + + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xDPMSSetTimeoutsReq); + + swaps(&stuff->standby); + swaps(&stuff->suspend); + swaps(&stuff->off); + return ProcDPMSSetTimeouts(client); +} + +static int +SProcDPMSEnable(client) +ClientPtr client; +{ + REQUEST(xDPMSEnableReq); + + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xDPMSEnableReq); + + return ProcDPMSEnable(client); +} + +static int +SProcDPMSDisable(client) +ClientPtr client; +{ + REQUEST(xDPMSDisableReq); + + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xDPMSDisableReq); + + return ProcDPMSDisable(client); +} + +static int +SProcDPMSForceLevel(client) +ClientPtr client; +{ + REQUEST(xDPMSForceLevelReq); + + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xDPMSForceLevelReq); + + swaps(&stuff->level); + + return ProcDPMSForceLevel(client); +} + +static int +SProcDPMSInfo(client) +ClientPtr client; +{ + REQUEST(xDPMSInfoReq); + + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xDPMSInfoReq); + + return ProcDPMSInfo(client); +} + +static int +SProcDPMSDispatch(client) +ClientPtr client; +{ + REQUEST(xReq); + switch (stuff->data) { + case X_DPMSGetVersion: + return SProcDPMSGetVersion(client); + case X_DPMSCapable: + return SProcDPMSCapable(client); + case X_DPMSGetTimeouts: + return SProcDPMSGetTimeouts(client); + case X_DPMSSetTimeouts: + return SProcDPMSSetTimeouts(client); + case X_DPMSEnable: + return SProcDPMSEnable(client); + case X_DPMSDisable: + return SProcDPMSDisable(client); + case X_DPMSForceLevel: + return SProcDPMSForceLevel(client); + case X_DPMSInfo: + return SProcDPMSInfo(client); + default: + return BadRequest; + } +} diff --git a/Xext/dpmsproc.h b/Xext/dpmsproc.h new file mode 100644 index 0000000..46c65d4 --- /dev/null +++ b/Xext/dpmsproc.h @@ -0,0 +1,15 @@ + +/* Prototypes for functions that the DDX must provide */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#ifndef _DPMSPROC_H_ +#define _DPMSPROC_H_ + +void DPMSSet(int level); + +Bool DPMSSupported(void); + +#endif diff --git a/Xext/saver.c b/Xext/saver.c new file mode 100644 index 0000000..293f013 --- /dev/null +++ b/Xext/saver.c @@ -0,0 +1,1427 @@ +/* + * +Copyright (c) 1992 X Consortium + +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, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +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 +X CONSORTIUM 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 X Consortium 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 X Consortium. + * + * Author: Keith Packard, MIT X Consortium + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#include +#include "misc.h" +#include "os.h" +#include "windowstr.h" +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "extnsionst.h" +#include "dixstruct.h" +#include "resource.h" +#include "opaque.h" +#include +#include "gcstruct.h" +#include "cursorstr.h" +#include "colormapst.h" +#ifdef DPMSExtension +#define DPMS_SERVER +#include +#endif + +#include + +#include "extinit.h" + +#if 0 +static unsigned char ScreenSaverReqCode = 0; +#endif +static int ScreenSaverEventBase = 0; + +extern DISPATCH_PROC(ProcScreenSaverQueryInfo); + +static DISPATCH_PROC(ProcScreenSaverDispatch); + +static DISPATCH_PROC(ProcScreenSaverQueryVersion); + +static DISPATCH_PROC(ProcScreenSaverSelectInput); + +static DISPATCH_PROC(ProcScreenSaverSetAttributes); + +static DISPATCH_PROC(ProcScreenSaverUnsetAttributes); + +static DISPATCH_PROC(ProcScreenSaverSuspend); + +static DISPATCH_PROC(SProcScreenSaverDispatch); + +static DISPATCH_PROC(SProcScreenSaverQueryInfo); + +static DISPATCH_PROC(SProcScreenSaverQueryVersion); + +static DISPATCH_PROC(SProcScreenSaverSelectInput); + +static DISPATCH_PROC(SProcScreenSaverSetAttributes); + +static DISPATCH_PROC(SProcScreenSaverUnsetAttributes); + +static DISPATCH_PROC(SProcScreenSaverSuspend); + +static Bool ScreenSaverHandle(ScreenPtr /* pScreen */ , + int /* xstate */ , + Bool /* force */ + ); + +static Bool + CreateSaverWindow(ScreenPtr /* pScreen */ + ); + +static Bool + DestroySaverWindow(ScreenPtr /* pScreen */ + ); + +static void + UninstallSaverColormap(ScreenPtr /* pScreen */ + ); + +static void + CheckScreenPrivate(ScreenPtr /* pScreen */ + ); + +static void SScreenSaverNotifyEvent(xScreenSaverNotifyEvent * /* from */ , + xScreenSaverNotifyEvent * /* to */ + ); + +static void ScreenSaverResetProc(ExtensionEntry * /* extEntry */ + ); + +static RESTYPE SuspendType; /* resource type for suspension records */ + +typedef struct _ScreenSaverSuspension *ScreenSaverSuspensionPtr; + +/* List of clients that are suspending the screensaver. */ +static ScreenSaverSuspensionPtr suspendingClients = NULL; + +/* + * clientResource is a resource ID that's added when the record is + * allocated, so the record is freed and the screensaver resumed when + * the client disconnects. count is the number of times the client has + * requested the screensaver be suspended. + */ +typedef struct _ScreenSaverSuspension { + ScreenSaverSuspensionPtr next; + ClientPtr pClient; + XID clientResource; + int count; +} ScreenSaverSuspensionRec; + +static int ScreenSaverFreeSuspend(pointer /*value */ , + XID /* id */ + ); + +/* + * each screen has a list of clients requesting + * ScreenSaverNotify events. Each client has a resource + * for each screen it selects ScreenSaverNotify input for, + * this resource is used to delete the ScreenSaverNotifyRec + * entry from the per-screen queue. + */ + +static RESTYPE EventType; /* resource type for event masks */ + +typedef struct _ScreenSaverEvent *ScreenSaverEventPtr; + +typedef struct _ScreenSaverEvent { + ScreenSaverEventPtr next; + ClientPtr client; + ScreenPtr screen; + XID resource; + CARD32 mask; +} ScreenSaverEventRec; + +static int ScreenSaverFreeEvents(pointer /* value */ , + XID /* id */ + ); + +static Bool setEventMask(ScreenPtr /* pScreen */ , + ClientPtr /* client */ , + unsigned long /* mask */ + ); + +static unsigned long getEventMask(ScreenPtr /* pScreen */ , + ClientPtr /* client */ + ); + +/* + * when a client sets the screen saver attributes, a resource is + * kept to be freed when the client exits + */ + +static RESTYPE AttrType; /* resource type for attributes */ + +typedef struct _ScreenSaverAttr { + ScreenPtr screen; + ClientPtr client; + XID resource; + short x, y; + unsigned short width, height, borderWidth; + unsigned char class; + unsigned char depth; + VisualID visual; + CursorPtr pCursor; + PixmapPtr pBackgroundPixmap; + PixmapPtr pBorderPixmap; + Colormap colormap; + unsigned long mask; /* no pixmaps or cursors */ + unsigned long *values; +} ScreenSaverAttrRec, *ScreenSaverAttrPtr; + +static int ScreenSaverFreeAttr(pointer /* value */ , + XID /* id */ + ); + +static void FreeAttrs(ScreenSaverAttrPtr /* pAttr */ + ); + +static void FreeScreenAttr(ScreenSaverAttrPtr /* pAttr */ + ); + +static void + SendScreenSaverNotify(ScreenPtr /* pScreen */ , + int /* state */ , + Bool /* forced */ + ); + +typedef struct _ScreenSaverScreenPrivate { + ScreenSaverEventPtr events; + ScreenSaverAttrPtr attr; + Bool hasWindow; + Colormap installedMap; +} ScreenSaverScreenPrivateRec, *ScreenSaverScreenPrivatePtr; + +static ScreenSaverScreenPrivatePtr MakeScreenPrivate(ScreenPtr /* pScreen */ + ); + +static int ScreenPrivateIndex; + +#define GetScreenPrivate(s) ((ScreenSaverScreenPrivatePtr)(s)->devPrivates[ScreenPrivateIndex].ptr) +#define SetScreenPrivate(s,v) ((s)->devPrivates[ScreenPrivateIndex].ptr = (pointer) v); +#define SetupScreen(s) ScreenSaverScreenPrivatePtr pPriv = (s ? GetScreenPrivate(s) : NULL) + +#define New(t) (malloc(sizeof (t))) + +/**************** + * ScreenSaverExtensionInit + * + * Called from InitExtensions in main() or from QueryExtension() if the + * extension is dynamically loaded. + * + ****************/ + +void +ScreenSaverExtensionInit(INITARGS) +{ + ExtensionEntry *extEntry; + + int i; + + ScreenPtr pScreen; + + AttrType = CreateNewResourceType(ScreenSaverFreeAttr); + EventType = CreateNewResourceType(ScreenSaverFreeEvents); + SuspendType = CreateNewResourceType(ScreenSaverFreeSuspend); + ScreenPrivateIndex = AllocateScreenPrivateIndex(); + + for (i = 0; i < screenInfo.numScreens; i++) { + pScreen = screenInfo.screens[i]; + SetScreenPrivate(pScreen, NULL); + } + if (AttrType && EventType && SuspendType && ScreenPrivateIndex != -1 && + (extEntry = AddExtension(ScreenSaverName, ScreenSaverNumberEvents, 0, + ProcScreenSaverDispatch, + SProcScreenSaverDispatch, ScreenSaverResetProc, + StandardMinorOpcode))) { +#if 0 + ScreenSaverReqCode = (unsigned char) extEntry->base; +#endif + ScreenSaverEventBase = extEntry->eventBase; + EventSwapVector[ScreenSaverEventBase] = + (EventSwapPtr) SScreenSaverNotifyEvent; + } +} + + /*ARGSUSED*/ static void +ScreenSaverResetProc(extEntry) +ExtensionEntry *extEntry; +{ +} + +static void +CheckScreenPrivate(pScreen) +ScreenPtr pScreen; +{ + SetupScreen(pScreen); + + if (!pPriv) + return; + if (!pPriv->attr && !pPriv->events && + !pPriv->hasWindow && pPriv->installedMap == None) { + free(pPriv); + SetScreenPrivate(pScreen, NULL); + savedScreenInfo[pScreen->myNum].ExternalScreenSaver = NULL; + } +} + +static ScreenSaverScreenPrivatePtr +MakeScreenPrivate(pScreen) +ScreenPtr pScreen; +{ + SetupScreen(pScreen); + + if (pPriv) + return pPriv; + pPriv = New(ScreenSaverScreenPrivateRec); + if (!pPriv) + return 0; + pPriv->events = 0; + pPriv->attr = 0; + pPriv->hasWindow = FALSE; + pPriv->installedMap = None; + SetScreenPrivate(pScreen, pPriv); + savedScreenInfo[pScreen->myNum].ExternalScreenSaver = ScreenSaverHandle; + return pPriv; +} + +static unsigned long +getEventMask(pScreen, client) +ScreenPtr pScreen; + +ClientPtr client; +{ + SetupScreen(pScreen); + ScreenSaverEventPtr pEv; + + if (!pPriv) + return 0; + for (pEv = pPriv->events; pEv; pEv = pEv->next) + if (pEv->client == client) + return pEv->mask; + return 0; +} + +static Bool +setEventMask(pScreen, client, mask) +ScreenPtr pScreen; + +ClientPtr client; + +unsigned long mask; +{ + SetupScreen(pScreen); + ScreenSaverEventPtr pEv, *pPrev; + + if (getEventMask(pScreen, client) == mask) + return TRUE; + if (!pPriv) { + pPriv = MakeScreenPrivate(pScreen); + if (!pPriv) + return FALSE; + } + for (pPrev = &pPriv->events; (pEv = *pPrev) != 0; pPrev = &pEv->next) + if (pEv->client == client) + break; + if (mask == 0) { + FreeResource(pEv->resource, EventType); + *pPrev = pEv->next; + free(pEv); + CheckScreenPrivate(pScreen); + } + else { + if (!pEv) { + pEv = New(ScreenSaverEventRec); + if (!pEv) { + CheckScreenPrivate(pScreen); + return FALSE; + } + *pPrev = pEv; + pEv->next = NULL; + pEv->client = client; + pEv->screen = pScreen; + pEv->resource = FakeClientID(client->index); + if (!AddResource(pEv->resource, EventType, (pointer) pEv)) + return FALSE; + } + pEv->mask = mask; + } + return TRUE; +} + +static void +FreeAttrs(pAttr) +ScreenSaverAttrPtr pAttr; +{ + PixmapPtr pPixmap; + + CursorPtr pCursor; + + if ((pPixmap = pAttr->pBackgroundPixmap) != 0) + (*pPixmap->drawable.pScreen->DestroyPixmap) (pPixmap); + if ((pPixmap = pAttr->pBorderPixmap) != 0) + (*pPixmap->drawable.pScreen->DestroyPixmap) (pPixmap); + if ((pCursor = pAttr->pCursor) != 0) + FreeCursor(pCursor, (Cursor) 0); +} + +static void +FreeScreenAttr(pAttr) +ScreenSaverAttrPtr pAttr; +{ + FreeAttrs(pAttr); + free(pAttr->values); + free(pAttr); +} + +static int +ScreenSaverFreeEvents(value, id) +pointer value; + +XID id; +{ + ScreenSaverEventPtr pOld = (ScreenSaverEventPtr) value; + + ScreenPtr pScreen = pOld->screen; + + SetupScreen(pScreen); + ScreenSaverEventPtr pEv, *pPrev; + + if (!pPriv) + return TRUE; + for (pPrev = &pPriv->events; (pEv = *pPrev) != 0; pPrev = &pEv->next) + if (pEv == pOld) + break; + if (!pEv) + return TRUE; + *pPrev = pEv->next; + free(pEv); + CheckScreenPrivate(pScreen); + return TRUE; +} + +static int +ScreenSaverFreeAttr(value, id) +pointer value; + +XID id; +{ + ScreenSaverAttrPtr pOldAttr = (ScreenSaverAttrPtr) value; + + ScreenPtr pScreen = pOldAttr->screen; + + SetupScreen(pScreen); + + if (!pPriv) + return TRUE; + if (pPriv->attr != pOldAttr) + return TRUE; + FreeScreenAttr(pOldAttr); + pPriv->attr = NULL; + if (pPriv->hasWindow) { + SaveScreens(SCREEN_SAVER_FORCER, ScreenSaverReset); + SaveScreens(SCREEN_SAVER_FORCER, ScreenSaverActive); + } + CheckScreenPrivate(pScreen); + return TRUE; +} + +static int +ScreenSaverFreeSuspend(pointer value, XID id) +{ + ScreenSaverSuspensionPtr data = (ScreenSaverSuspensionPtr) value; + + ScreenSaverSuspensionPtr *prev, this; + + /* Unlink and free the suspension record for the client */ + for (prev = &suspendingClients; (this = *prev); prev = &this->next) { + if (this == data) { + *prev = this->next; + free(this); + break; + } + } + + /* Reenable the screensaver if this was the last client suspending it. */ + if (screenSaverSuspended && suspendingClients == NULL) { + screenSaverSuspended = FALSE; + + /* The screensaver could be active, since suspending it (by design) + doesn't prevent it from being forceably activated */ +#ifdef DPMSExtension + if (screenIsSaved != SCREEN_SAVER_ON && DPMSPowerLevel == DPMSModeOn) +#else + if (screenIsSaved != SCREEN_SAVER_ON) +#endif + { + UpdateCurrentTimeIf(); + lastDeviceEventTime = currentTime; + SetScreenSaverTimer(); + } + } + + return Success; +} + +static void +SendScreenSaverNotify(pScreen, state, forced) +ScreenPtr pScreen; + +int state; + +Bool forced; +{ + ScreenSaverScreenPrivatePtr pPriv; + + ScreenSaverEventPtr pEv; + + unsigned long mask; + + xScreenSaverNotifyEvent ev; + + ClientPtr client; + + int kind; + + UpdateCurrentTimeIf(); + mask = ScreenSaverNotifyMask; + if (state == ScreenSaverCycle) + mask = ScreenSaverCycleMask; + pScreen = screenInfo.screens[pScreen->myNum]; + pPriv = GetScreenPrivate(pScreen); + if (!pPriv) + return; + if (pPriv->attr) + kind = ScreenSaverExternal; + else if (ScreenSaverBlanking != DontPreferBlanking) + kind = ScreenSaverBlanked; + else + kind = ScreenSaverInternal; + for (pEv = pPriv->events; pEv; pEv = pEv->next) { + client = pEv->client; + if (client->clientGone) + continue; + if (!(pEv->mask & mask)) + continue; + ev.type = ScreenSaverNotify + ScreenSaverEventBase; + ev.state = state; + ev.sequenceNumber = client->sequence; + ev.timestamp = currentTime.milliseconds; + ev.root = WindowTable[pScreen->myNum]->drawable.id; + ev.window = savedScreenInfo[pScreen->myNum].wid; + ev.kind = kind; + ev.forced = forced; + WriteEventsToClient(client, 1, (xEvent *) &ev); + } +} + +static void +SScreenSaverNotifyEvent(from, to) +xScreenSaverNotifyEvent *from, *to; +{ + to->type = from->type; + to->state = from->state; + cpswaps(from->sequenceNumber, to->sequenceNumber); + cpswapl(from->timestamp, to->timestamp); + cpswapl(from->root, to->root); + cpswapl(from->window, to->window); + to->kind = from->kind; + to->forced = from->forced; +} + +static void +UninstallSaverColormap(pScreen) +ScreenPtr pScreen; +{ + SetupScreen(pScreen); + ColormapPtr pCmap; + + if (pPriv && pPriv->installedMap != None) { + pCmap = (ColormapPtr) LookupIDByType(pPriv->installedMap, RT_COLORMAP); + if (pCmap) + (*pCmap->pScreen->UninstallColormap) (pCmap); + pPriv->installedMap = None; + CheckScreenPrivate(pScreen); + } +} + +static Bool +CreateSaverWindow(pScreen) +ScreenPtr pScreen; +{ + SetupScreen(pScreen); + ScreenSaverStuffPtr pSaver; + + ScreenSaverAttrPtr pAttr; + + WindowPtr pWin; + + int result; + + unsigned long mask; + + Colormap *installedMaps; + + int numInstalled; + + int i; + + Colormap wantMap; + + ColormapPtr pCmap; + + pSaver = &savedScreenInfo[pScreen->myNum]; + if (pSaver->pWindow) { + pSaver->pWindow = NullWindow; + FreeResource(pSaver->wid, RT_NONE); + if (pPriv) { + UninstallSaverColormap(pScreen); + pPriv->hasWindow = FALSE; + CheckScreenPrivate(pScreen); + } + } + + if (!pPriv || !(pAttr = pPriv->attr)) + return FALSE; + + pPriv->installedMap = None; + + if (GrabInProgress && GrabInProgress != pAttr->client->index) + return FALSE; + + pWin = CreateWindow(pSaver->wid, WindowTable[pScreen->myNum], + pAttr->x, pAttr->y, pAttr->width, pAttr->height, + pAttr->borderWidth, pAttr->class, + pAttr->mask, (XID *) pAttr->values, + pAttr->depth, serverClient, pAttr->visual, &result); + if (!pWin) + return FALSE; + + if (!AddResource(pWin->drawable.id, RT_WINDOW, pWin)) + return FALSE; + + mask = 0; + if (pAttr->pBackgroundPixmap) { + pWin->backgroundState = BackgroundPixmap; + pWin->background.pixmap = pAttr->pBackgroundPixmap; + pAttr->pBackgroundPixmap->refcnt++; + mask |= CWBackPixmap; + } + if (pAttr->pBorderPixmap) { + pWin->borderIsPixel = FALSE; + pWin->border.pixmap = pAttr->pBorderPixmap; + pAttr->pBorderPixmap->refcnt++; + mask |= CWBorderPixmap; + } + if (pAttr->pCursor) { + if (!pWin->optional) + if (!MakeWindowOptional(pWin)) { + FreeResource(pWin->drawable.id, RT_NONE); + return FALSE; + } + if (pWin->optional->cursor) + FreeCursor(pWin->optional->cursor, (Cursor) 0); + pWin->optional->cursor = pAttr->pCursor; + pAttr->pCursor->refcnt++; + pWin->cursorIsNone = FALSE; + CheckWindowOptionalNeed(pWin); + mask |= CWCursor; + } + if (mask) + (*pScreen->ChangeWindowAttributes) (pWin, mask); + + if (pAttr->colormap != None) + (void) ChangeWindowAttributes(pWin, CWColormap, &pAttr->colormap, + serverClient); + + MapWindow(pWin, serverClient); + + pPriv->hasWindow = TRUE; + pSaver->pWindow = pWin; + + /* check and install our own colormap if it isn't installed now */ + wantMap = wColormap(pWin); + if (wantMap == None) + return TRUE; + installedMaps = (Colormap *) ALLOCATE_LOCAL(pScreen->maxInstalledCmaps * + sizeof(Colormap)); + numInstalled = (*pWin->drawable.pScreen->ListInstalledColormaps) + (pScreen, installedMaps); + for (i = 0; i < numInstalled; i++) + if (installedMaps[i] == wantMap) + break; + + DEALLOCATE_LOCAL((char *) installedMaps); + + if (i < numInstalled) + return TRUE; + + pCmap = (ColormapPtr) LookupIDByType(wantMap, RT_COLORMAP); + if (!pCmap) + return TRUE; + + pPriv->installedMap = wantMap; + + (*pCmap->pScreen->InstallColormap) (pCmap); + + return TRUE; +} + +static Bool +DestroySaverWindow(pScreen) +ScreenPtr pScreen; +{ + SetupScreen(pScreen); + ScreenSaverStuffPtr pSaver; + + if (!pPriv || !pPriv->hasWindow) + return FALSE; + + pSaver = &savedScreenInfo[pScreen->myNum]; + if (pSaver->pWindow) { + pSaver->pWindow = NullWindow; + FreeResource(pSaver->wid, RT_NONE); + } + pPriv->hasWindow = FALSE; + CheckScreenPrivate(pScreen); + UninstallSaverColormap(pScreen); + return TRUE; +} + +static Bool +ScreenSaverHandle(pScreen, xstate, force) +ScreenPtr pScreen; + +int xstate; + +Bool force; +{ + int state = 0; + + Bool ret = FALSE; + + ScreenSaverScreenPrivatePtr pPriv; + + switch (xstate) { + case SCREEN_SAVER_ON: + state = ScreenSaverOn; + ret = CreateSaverWindow(pScreen); + break; + case SCREEN_SAVER_OFF: + state = ScreenSaverOff; + ret = DestroySaverWindow(pScreen); + break; + case SCREEN_SAVER_CYCLE: + state = ScreenSaverCycle; + pPriv = GetScreenPrivate(pScreen); + if (pPriv && pPriv->hasWindow) + ret = TRUE; + + } + SendScreenSaverNotify(pScreen, state, force); + return ret; +} + +static int +ProcScreenSaverQueryVersion(client) +ClientPtr client; +{ + xScreenSaverQueryVersionReply rep; + + + REQUEST_SIZE_MATCH(xScreenSaverQueryVersionReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.majorVersion = ScreenSaverMajorVersion; + rep.minorVersion = ScreenSaverMinorVersion; + if (client->swapped) { + swaps(&rep.sequenceNumber); + swapl(&rep.length); + } + WriteToClient(client, sizeof(xScreenSaverQueryVersionReply), (char *) &rep); + return (client->noClientException); +} + +int +ProcScreenSaverQueryInfo(client) +ClientPtr client; +{ + REQUEST(xScreenSaverQueryInfoReq); + xScreenSaverQueryInfoReply rep; + + + ScreenSaverStuffPtr pSaver; + + DrawablePtr pDraw; + + CARD32 lastInput; + + ScreenSaverScreenPrivatePtr pPriv; + + REQUEST_SIZE_MATCH(xScreenSaverQueryInfoReq); + pDraw = (DrawablePtr) LookupDrawable(stuff->drawable, client); + if (!pDraw) + return BadDrawable; + + pSaver = &savedScreenInfo[pDraw->pScreen->myNum]; + pPriv = GetScreenPrivate(pDraw->pScreen); + + UpdateCurrentTime(); + lastInput = GetTimeInMillis() - lastDeviceEventTime.milliseconds; + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.window = pSaver->wid; + if (screenIsSaved != SCREEN_SAVER_OFF) { + rep.state = ScreenSaverOn; + if (ScreenSaverTime) + rep.tilOrSince = lastInput - ScreenSaverTime; + else + rep.tilOrSince = 0; + } + else { + if (ScreenSaverTime) { + rep.state = ScreenSaverOff; + if (ScreenSaverTime < lastInput) + rep.tilOrSince = 0; + else + rep.tilOrSince = ScreenSaverTime - lastInput; + } + else { + rep.state = ScreenSaverDisabled; + rep.tilOrSince = 0; + } + } + rep.idle = lastInput; + rep.eventMask = getEventMask(pDraw->pScreen, client); + if (pPriv && pPriv->attr) + rep.kind = ScreenSaverExternal; + else if (ScreenSaverBlanking != DontPreferBlanking) + rep.kind = ScreenSaverBlanked; + else + rep.kind = ScreenSaverInternal; + if (client->swapped) { + swaps(&rep.sequenceNumber); + swapl(&rep.length); + swapl(&rep.window); + swapl(&rep.tilOrSince); + swapl(&rep.idle); + swapl(&rep.eventMask); + } + WriteToClient(client, sizeof(xScreenSaverQueryInfoReply), (char *) &rep); + return (client->noClientException); +} + +static int +ProcScreenSaverSelectInput(client) +ClientPtr client; +{ + REQUEST(xScreenSaverSelectInputReq); + DrawablePtr pDraw; + + REQUEST_SIZE_MATCH(xScreenSaverSelectInputReq); + pDraw = (DrawablePtr) LookupDrawable(stuff->drawable, client); + if (!pDraw) + return BadDrawable; + if (!setEventMask(pDraw->pScreen, client, stuff->eventMask)) + return BadAlloc; + return Success; +} + +static int +ScreenSaverSetAttributes(ClientPtr client) +{ + REQUEST(xScreenSaverSetAttributesReq); + DrawablePtr pDraw; + + WindowPtr pParent; + + ScreenPtr pScreen; + + ScreenSaverScreenPrivatePtr pPriv = 0; + + ScreenSaverAttrPtr pAttr = 0; + + int ret; + + int len; + + int class, bw, depth; + + unsigned long visual; + + int idepth, ivisual; + + Bool fOK; + + DepthPtr pDepth; + + WindowOptPtr ancwopt; + + unsigned int *pVlist; + + unsigned long *values = 0; + + unsigned long tmask, imask; + + unsigned long val; + + Pixmap pixID; + + PixmapPtr pPixmap; + + Cursor cursorID; + + CursorPtr pCursor; + + Colormap cmap; + + ColormapPtr pCmap; + + REQUEST_AT_LEAST_SIZE(xScreenSaverSetAttributesReq); + pDraw = (DrawablePtr) LookupDrawable(stuff->drawable, client); + if (!pDraw) + return BadDrawable; + pScreen = pDraw->pScreen; + pParent = WindowTable[pScreen->myNum]; + + len = stuff->length - (sizeof(xScreenSaverSetAttributesReq) >> 2); + if (Ones(stuff->mask) != len) + return BadLength; + if (!stuff->width || !stuff->height) { + client->errorValue = 0; + return BadValue; + } + switch (class = stuff->c_class) { + case CopyFromParent: + case InputOnly: + case InputOutput: + break; + default: + client->errorValue = class; + return BadValue; + } + bw = stuff->borderWidth; + depth = stuff->depth; + visual = stuff->visualID; + + /* copied directly from CreateWindow */ + + if (class == CopyFromParent) + class = pParent->drawable.class; + + if ((class != InputOutput) && (class != InputOnly)) { + client->errorValue = class; + return BadValue; + } + + if ((class != InputOnly) && (pParent->drawable.class == InputOnly)) + return BadMatch; + + if ((class == InputOnly) && ((bw != 0) || (depth != 0))) + return BadMatch; + + if ((class == InputOutput) && (depth == 0)) + depth = pParent->drawable.depth; + ancwopt = pParent->optional; + if (!ancwopt) + ancwopt = FindWindowWithOptional(pParent)->optional; + if (visual == CopyFromParent) + 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) + return BadMatch; + } + + if (((stuff->mask & (CWBorderPixmap | CWBorderPixel)) == 0) && + (class != InputOnly) && (depth != pParent->drawable.depth)) { + return BadMatch; + } + + if (((stuff->mask & CWColormap) == 0) && + (class != InputOnly) && + ((visual != ancwopt->visual) || (ancwopt->colormap == None))) { + return BadMatch; + } + + /* end of errors from CreateWindow */ + + pPriv = GetScreenPrivate(pScreen); + if (pPriv && pPriv->attr) { + if (pPriv->attr->client != client) + return BadAccess; + } + if (!pPriv) { + pPriv = MakeScreenPrivate(pScreen); + if (!pPriv) + return FALSE; + } + pAttr = New(ScreenSaverAttrRec); + if (!pAttr) { + ret = BadAlloc; + goto bail; + } + /* over allocate for override redirect */ + values = malloc((len + 1) * sizeof(unsigned long)); + if (!values) { + ret = BadAlloc; + goto bail; + } + pAttr->screen = pScreen; + pAttr->client = client; + pAttr->x = stuff->x; + pAttr->y = stuff->y; + pAttr->width = stuff->width; + pAttr->height = stuff->height; + pAttr->borderWidth = stuff->borderWidth; + pAttr->class = stuff->c_class; + pAttr->depth = depth; + pAttr->visual = visual; + pAttr->colormap = None; + pAttr->pCursor = NullCursor; + pAttr->pBackgroundPixmap = NullPixmap; + pAttr->pBorderPixmap = NullPixmap; + pAttr->values = values; + /* + * go through the mask, checking the values, + * looking up pixmaps and cursors and hold a reference + * to them. + */ + pAttr->mask = tmask = stuff->mask | CWOverrideRedirect; + pVlist = (unsigned int *) (stuff + 1); + while (tmask) { + imask = lowbit(tmask); + tmask &= ~imask; + switch (imask) { + case CWBackPixmap: + pixID = (Pixmap) * pVlist; + if (pixID == None) { + *values++ = None; + } + else if (pixID == ParentRelative) { + if (depth != pParent->drawable.depth) { + ret = BadMatch; + goto PatchUp; + } + *values++ = ParentRelative; + } + else { + pPixmap = (PixmapPtr) LookupIDByType(pixID, RT_PIXMAP); + if (pPixmap != (PixmapPtr) NULL) { + if ((pPixmap->drawable.depth != depth) || + (pPixmap->drawable.pScreen != pScreen)) { + ret = BadMatch; + goto PatchUp; + } + pAttr->pBackgroundPixmap = pPixmap; + pPixmap->refcnt++; + pAttr->mask &= ~CWBackPixmap; + } + else { + ret = BadPixmap; + client->errorValue = pixID; + goto PatchUp; + } + } + break; + case CWBackPixel: + *values++ = (CARD32) *pVlist; + break; + case CWBorderPixmap: + pixID = (Pixmap) * pVlist; + if (pixID == CopyFromParent) { + if (depth != pParent->drawable.depth) { + ret = BadMatch; + goto PatchUp; + } + *values++ = CopyFromParent; + } + else { + pPixmap = (PixmapPtr) LookupIDByType(pixID, RT_PIXMAP); + if (pPixmap) { + if ((pPixmap->drawable.depth != depth) || + (pPixmap->drawable.pScreen != pScreen)) { + ret = BadMatch; + goto PatchUp; + } + pAttr->pBorderPixmap = pPixmap; + pPixmap->refcnt++; + pAttr->mask &= ~CWBorderPixmap; + } + else { + ret = BadPixmap; + client->errorValue = pixID; + goto PatchUp; + } + } + break; + case CWBorderPixel: + *values++ = (CARD32) *pVlist; + break; + case CWBitGravity: + val = (CARD8) *pVlist; + if (val > StaticGravity) { + ret = BadValue; + client->errorValue = val; + goto PatchUp; + } + *values++ = val; + break; + case CWWinGravity: + val = (CARD8) *pVlist; + if (val > StaticGravity) { + ret = BadValue; + client->errorValue = val; + goto PatchUp; + } + *values++ = val; + break; + case CWBackingStore: + val = (CARD8) *pVlist; + if ((val != NotUseful) && (val != WhenMapped) && (val != Always)) { + ret = BadValue; + client->errorValue = val; + goto PatchUp; + } + *values++ = val; + break; + case CWBackingPlanes: + *values++ = (CARD32) *pVlist; + break; + case CWBackingPixel: + *values++ = (CARD32) *pVlist; + break; + case CWSaveUnder: + val = (BOOL) * pVlist; + if ((val != xTrue) && (val != xFalse)) { + ret = BadValue; + client->errorValue = val; + goto PatchUp; + } + *values++ = val; + break; + case CWEventMask: + *values++ = (CARD32) *pVlist; + break; + case CWDontPropagate: + *values++ = (CARD32) *pVlist; + break; + case CWOverrideRedirect: + if (!(stuff->mask & CWOverrideRedirect)) + pVlist--; + else { + val = (BOOL) * pVlist; + if ((val != xTrue) && (val != xFalse)) { + ret = BadValue; + client->errorValue = val; + goto PatchUp; + } + } + *values++ = xTrue; + break; + case CWColormap: + cmap = (Colormap) * pVlist; + pCmap = (ColormapPtr) LookupIDByType(cmap, RT_COLORMAP); + if (!pCmap) { + ret = BadColor; + client->errorValue = cmap; + goto PatchUp; + } + if (pCmap->pVisual->vid != visual || pCmap->pScreen != pScreen) { + ret = BadMatch; + goto PatchUp; + } + pAttr->colormap = cmap; + pAttr->mask &= ~CWColormap; + break; + case CWCursor: + cursorID = (Cursor) * pVlist; + if (cursorID == None) { + *values++ = None; + } + else { + pCursor = (CursorPtr) LookupIDByType(cursorID, RT_CURSOR); + if (!pCursor) { + ret = BadCursor; + client->errorValue = cursorID; + goto PatchUp; + } + pCursor->refcnt++; + pAttr->pCursor = pCursor; + pAttr->mask &= ~CWCursor; + } + break; + default: + ret = BadValue; + client->errorValue = stuff->mask; + goto PatchUp; + } + pVlist++; + } + if (pPriv->attr) + FreeScreenAttr(pPriv->attr); + pPriv->attr = pAttr; + pAttr->resource = FakeClientID(client->index); + if (!AddResource(pAttr->resource, AttrType, (pointer) pAttr)) + return BadAlloc; + return Success; + PatchUp: + FreeAttrs(pAttr); + bail: + CheckScreenPrivate(pScreen); + if (pAttr) + free(pAttr->values); + free(pAttr); + return ret; +} + +static int +ScreenSaverUnsetAttributes(ClientPtr client) +{ + REQUEST(xScreenSaverSetAttributesReq); + DrawablePtr pDraw; + + ScreenSaverScreenPrivatePtr pPriv; + + REQUEST_SIZE_MATCH(xScreenSaverUnsetAttributesReq); + pDraw = (DrawablePtr) LookupDrawable(stuff->drawable, client); + if (!pDraw) + return BadDrawable; + pPriv = GetScreenPrivate(pDraw->pScreen); + if (pPriv && pPriv->attr && pPriv->attr->client == client) { + FreeResource(pPriv->attr->resource, AttrType); + FreeScreenAttr(pPriv->attr); + pPriv->attr = NULL; + CheckScreenPrivate(pDraw->pScreen); + } + return Success; +} + +static int +ProcScreenSaverSetAttributes(ClientPtr client) +{ + + return ScreenSaverSetAttributes(client); +} + +static int +ProcScreenSaverUnsetAttributes(ClientPtr client) +{ + + return ScreenSaverUnsetAttributes(client); +} + +static int +ProcScreenSaverSuspend(ClientPtr client) +{ + ScreenSaverSuspensionPtr *prev, this; + + REQUEST(xScreenSaverSuspendReq); + REQUEST_SIZE_MATCH(xScreenSaverSuspendReq); + + /* Check if this client is suspending the screensaver */ + for (prev = &suspendingClients; (this = *prev); prev = &this->next) + if (this->pClient == client) + break; + + if (this) { + if (stuff->suspend == TRUE) + this->count++; + else if (--this->count == 0) + FreeResource(this->clientResource, RT_NONE); + + return Success; + } + + /* If we get to this point, this client isn't suspending the screensaver */ + if (stuff->suspend == FALSE) + return Success; + + /* + * Allocate a suspension record for the client, and stop the screensaver + * if it isn't already suspended by another client. We attach a resource ID + * to the record, so the screensaver will be reenabled and the record freed + * if the client disconnects without reenabling it first. + */ + this = malloc(sizeof(ScreenSaverSuspensionRec)); + + if (!this) + return BadAlloc; + + this->next = NULL; + this->pClient = client; + this->count = 1; + this->clientResource = FakeClientID(client->index); + + if (!AddResource(this->clientResource, SuspendType, (pointer) this)) { + free(this); + return BadAlloc; + } + + *prev = this; + if (!screenSaverSuspended) { + screenSaverSuspended = TRUE; + FreeScreenSaverTimer(); + } + + return (client->noClientException); +} + +static DISPATCH_PROC((*NormalVector[])) = { +ProcScreenSaverQueryVersion, + ProcScreenSaverQueryInfo, + ProcScreenSaverSelectInput, + ProcScreenSaverSetAttributes, + ProcScreenSaverUnsetAttributes, ProcScreenSaverSuspend,}; + +#define NUM_REQUESTS ((sizeof NormalVector) / (sizeof NormalVector[0])) + +static int +ProcScreenSaverDispatch(client) +ClientPtr client; +{ + REQUEST(xReq); + + if (stuff->data < NUM_REQUESTS) + return (*NormalVector[stuff->data]) (client); + return BadRequest; +} + +static int +SProcScreenSaverQueryVersion(client) +ClientPtr client; +{ + REQUEST(xScreenSaverQueryVersionReq); + + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xScreenSaverQueryVersionReq); + return ProcScreenSaverQueryVersion(client); +} + +static int +SProcScreenSaverQueryInfo(client) +ClientPtr client; +{ + REQUEST(xScreenSaverQueryInfoReq); + + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xScreenSaverQueryInfoReq); + swapl(&stuff->drawable); + return ProcScreenSaverQueryInfo(client); +} + +static int +SProcScreenSaverSelectInput(client) +ClientPtr client; +{ + REQUEST(xScreenSaverSelectInputReq); + + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xScreenSaverSelectInputReq); + swapl(&stuff->drawable); + swapl(&stuff->eventMask); + return ProcScreenSaverSelectInput(client); +} + +static int +SProcScreenSaverSetAttributes(client) +ClientPtr client; +{ + REQUEST(xScreenSaverSetAttributesReq); + + swaps(&stuff->length); + REQUEST_AT_LEAST_SIZE(xScreenSaverSetAttributesReq); + swapl(&stuff->drawable); + swaps(&stuff->x); + swaps(&stuff->y); + swaps(&stuff->width); + swaps(&stuff->height); + swaps(&stuff->borderWidth); + swapl(&stuff->visualID); + swapl(&stuff->mask); + SwapRestL(stuff); + return ProcScreenSaverSetAttributes(client); +} + +static int +SProcScreenSaverUnsetAttributes(client) +ClientPtr client; +{ + REQUEST(xScreenSaverUnsetAttributesReq); + + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xScreenSaverUnsetAttributesReq); + swapl(&stuff->drawable); + return ProcScreenSaverUnsetAttributes(client); +} + +static int +SProcScreenSaverSuspend(ClientPtr client) +{ + REQUEST(xScreenSaverSuspendReq); + + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xScreenSaverSuspendReq); + return ProcScreenSaverSuspend(client); +} + +static DISPATCH_PROC((*SwappedVector[])) = { +SProcScreenSaverQueryVersion, + SProcScreenSaverQueryInfo, + SProcScreenSaverSelectInput, + SProcScreenSaverSetAttributes, + SProcScreenSaverUnsetAttributes, SProcScreenSaverSuspend,}; + +static int +SProcScreenSaverDispatch(client) +ClientPtr client; +{ + REQUEST(xReq); + + if (stuff->data < NUM_REQUESTS) + return (*SwappedVector[stuff->data]) (client); + return BadRequest; +} diff --git a/Xext/shape.c b/Xext/shape.c new file mode 100644 index 0000000..af2aab5 --- /dev/null +++ b/Xext/shape.c @@ -0,0 +1,1241 @@ +/************************************************************ + +Copyright 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. + +********************************************************/ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include + +#include +#include +#include "misc.h" +#include "os.h" +#include "windowstr.h" +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "extnsionst.h" +#include "dixstruct.h" +#include "resource.h" +#include "opaque.h" +#define _SHAPE_SERVER_ /* don't want Xlib structures */ +#include +#include "regionstr.h" +#include "gcstruct.h" +#include "extinit.h" + +typedef RegionPtr (*CreateDftPtr) (WindowPtr /* pWin */ + ); + +static int ShapeFreeClient(pointer /* data */ , + XID /* id */ + ); + +static int ShapeFreeEvents(pointer /* data */ , + XID /* id */ + ); + +static void ShapeResetProc(ExtensionEntry * /* extEntry */ + ); + +static void SShapeNotifyEvent(xShapeNotifyEvent * /* from */ , + xShapeNotifyEvent * /* to */ + ); + +static int + RegionOperate(ClientPtr /* client */ , + WindowPtr /* pWin */ , + int /* kind */ , + RegionPtr * /* destRgnp */ , + RegionPtr /* srcRgn */ , + int /* op */ , + int /* xoff */ , + int /* yoff */ , + CreateDftPtr /* create */ + ); + +/* SendShapeNotify, CreateBoundingShape and CreateClipShape are used + * externally by the Xfixes extension and are now defined in window.h + */ + +static DISPATCH_PROC(ProcShapeCombine); + +static DISPATCH_PROC(ProcShapeDispatch); + +static DISPATCH_PROC(ProcShapeGetRectangles); + +static DISPATCH_PROC(ProcShapeInputSelected); + +static DISPATCH_PROC(ProcShapeMask); + +static DISPATCH_PROC(ProcShapeOffset); + +static DISPATCH_PROC(ProcShapeQueryExtents); + +static DISPATCH_PROC(ProcShapeQueryVersion); + +static DISPATCH_PROC(ProcShapeRectangles); + +static DISPATCH_PROC(ProcShapeSelectInput); + +static DISPATCH_PROC(SProcShapeCombine); + +static DISPATCH_PROC(SProcShapeDispatch); + +static DISPATCH_PROC(SProcShapeGetRectangles); + +static DISPATCH_PROC(SProcShapeInputSelected); + +static DISPATCH_PROC(SProcShapeMask); + +static DISPATCH_PROC(SProcShapeOffset); + +static DISPATCH_PROC(SProcShapeQueryExtents); + +static DISPATCH_PROC(SProcShapeQueryVersion); + +static DISPATCH_PROC(SProcShapeRectangles); + +static DISPATCH_PROC(SProcShapeSelectInput); + + +#if 0 +static unsigned char ShapeReqCode = 0; +#endif +static int ShapeEventBase = 0; + +static RESTYPE ClientType, EventType; /* resource types for event masks */ + +/* + * each window has a list of clients requesting + * ShapeNotify events. Each client has a resource + * for each window it selects ShapeNotify input for, + * this resource is used to delete the ShapeNotifyRec + * entry from the per-window queue. + */ + +typedef struct _ShapeEvent *ShapeEventPtr; + +typedef struct _ShapeEvent { + ShapeEventPtr next; + ClientPtr client; + WindowPtr window; + XID clientResource; +} ShapeEventRec; + +/**************** + * ShapeExtensionInit + * + * Called from InitExtensions in main() or from QueryExtension() if the + * extension is dynamically loaded. + * + ****************/ + +void +ShapeExtensionInit(void) +{ + ExtensionEntry *extEntry; + + ClientType = CreateNewResourceType(ShapeFreeClient); + EventType = CreateNewResourceType(ShapeFreeEvents); + if (ClientType && EventType && + (extEntry = AddExtension(SHAPENAME, ShapeNumberEvents, 0, + ProcShapeDispatch, SProcShapeDispatch, + ShapeResetProc, StandardMinorOpcode))) { +#if 0 + ShapeReqCode = (unsigned char) extEntry->base; +#endif + ShapeEventBase = extEntry->eventBase; + EventSwapVector[ShapeEventBase] = (EventSwapPtr) SShapeNotifyEvent; + } +} + + /*ARGSUSED*/ static void +ShapeResetProc(extEntry) +ExtensionEntry *extEntry; +{ +} + +static int +RegionOperate(client, pWin, kind, destRgnp, srcRgn, op, xoff, yoff, create) +ClientPtr client; + +WindowPtr pWin; + +int kind; + +RegionPtr *destRgnp, srcRgn; + +int op; + +int xoff, yoff; + +CreateDftPtr create; /* creates a reasonable *destRgnp */ +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + + if (srcRgn && (xoff || yoff)) + REGION_TRANSLATE(srcRgn, xoff, yoff); + if (!pWin->parent) { + if (srcRgn) + REGION_DESTROY(srcRgn); + return Success; + } + + /* May/30/2001: + * The shape.PS specs say if src is None, existing shape is to be + * removed (and so the op-code has no meaning in such removal); + * see shape.PS, page 3, ShapeMask. + */ + if (srcRgn == NULL) { + if (*destRgnp != NULL) { + REGION_DESTROY(*destRgnp); + *destRgnp = 0; + /* go on to remove shape and generate ShapeNotify */ + } + else { + /* May/30/2001: + * The target currently has no shape in effect, so nothing to + * do here. The specs say that ShapeNotify is generated whenever + * the client region is "modified"; since no modification is done + * here, we do not generate that event. The specs does not say + * "it is an error to request removal when there is no shape in + * effect", so we return good status. + */ + return Success; + } + } + else + switch (op) { + case ShapeSet: + if (*destRgnp) + REGION_DESTROY(*destRgnp); + *destRgnp = srcRgn; + srcRgn = 0; + break; + case ShapeUnion: + if (*destRgnp) + REGION_UNION(*destRgnp, *destRgnp, srcRgn); + break; + case ShapeIntersect: + if (*destRgnp) + REGION_INTERSECT(*destRgnp, *destRgnp, srcRgn); + else { + *destRgnp = srcRgn; + srcRgn = 0; + } + break; + case ShapeSubtract: + if (!*destRgnp) + *destRgnp = (*create) (pWin); + REGION_SUBTRACT(*destRgnp, *destRgnp, srcRgn); + break; + case ShapeInvert: + if (!*destRgnp) + *destRgnp = REGION_CREATE((BoxPtr) 0, 0); + else + REGION_SUBTRACT(*destRgnp, srcRgn, *destRgnp); + break; + default: + client->errorValue = op; + return BadValue; + } + if (srcRgn) + REGION_DESTROY(srcRgn); + (*pScreen->SetShape) (pWin); + SendShapeNotify(pWin, kind); + return Success; +} + +RegionPtr +CreateBoundingShape(pWin) +WindowPtr pWin; +{ + BoxRec extents; + + extents.x1 = -wBorderWidth(pWin); + extents.y1 = -wBorderWidth(pWin); + extents.x2 = pWin->drawable.width + wBorderWidth(pWin); + extents.y2 = pWin->drawable.height + wBorderWidth(pWin); + return REGION_CREATE(&extents, 1); +} + +RegionPtr +CreateClipShape(pWin) +WindowPtr pWin; +{ + BoxRec extents; + + extents.x1 = 0; + extents.y1 = 0; + extents.x2 = pWin->drawable.width; + extents.y2 = pWin->drawable.height; + return REGION_CREATE(&extents, 1); +} + +static int +ProcShapeQueryVersion(client) +ClientPtr client; +{ + xShapeQueryVersionReply rep; + + REQUEST_SIZE_MATCH(xShapeQueryVersionReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.majorVersion = SHAPE_MAJOR_VERSION; + rep.minorVersion = SHAPE_MINOR_VERSION; + if (client->swapped) { + swaps(&rep.sequenceNumber); + swapl(&rep.length); + swaps(&rep.majorVersion); + swaps(&rep.minorVersion); + } + WriteToClient(client, sizeof(xShapeQueryVersionReply), (char *) &rep); + return (client->noClientException); +} + +/***************** + * ProcShapeRectangles + * + *****************/ + +static int +ProcShapeRectangles(client) +ClientPtr client; +{ + WindowPtr pWin; + + REQUEST(xShapeRectanglesReq); + xRectangle *prects; + + int nrects, ctype; + + RegionPtr srcRgn; + + RegionPtr *destRgn; + + CreateDftPtr createDefault; + + REQUEST_AT_LEAST_SIZE(xShapeRectanglesReq); + UpdateCurrentTime(); + pWin = LookupWindow(stuff->dest, client); + if (!pWin) + return BadWindow; + switch (stuff->destKind) { + case ShapeBounding: + createDefault = CreateBoundingShape; + break; + case ShapeClip: + createDefault = CreateClipShape; + break; + case ShapeInput: + createDefault = CreateBoundingShape; + break; + default: + client->errorValue = stuff->destKind; + return BadValue; + } + if ((stuff->ordering != Unsorted) && (stuff->ordering != YSorted) && + (stuff->ordering != YXSorted) && (stuff->ordering != YXBanded)) { + client->errorValue = stuff->ordering; + return BadValue; + } + nrects = ((stuff->length << 2) - sizeof(xShapeRectanglesReq)); + if (nrects & 4) + return BadLength; + nrects >>= 3; + prects = (xRectangle *) &stuff[1]; + ctype = VerifyRectOrder(nrects, prects, (int) stuff->ordering); + if (ctype < 0) + return BadMatch; + srcRgn = RECTS_TO_REGION(nrects, prects, ctype); + + if (!pWin->optional) + MakeWindowOptional(pWin); + switch (stuff->destKind) { + case ShapeBounding: + destRgn = &pWin->optional->boundingShape; + break; + case ShapeClip: + destRgn = &pWin->optional->clipShape; + break; + case ShapeInput: + destRgn = &pWin->optional->inputShape; + break; + default: + return BadValue; + } + + return RegionOperate(client, pWin, (int) stuff->destKind, + destRgn, srcRgn, (int) stuff->op, + stuff->xOff, stuff->yOff, createDefault); +} + + +/************** + * ProcShapeMask + **************/ + +static int +ProcShapeMask(client) +ClientPtr client; +{ + WindowPtr pWin; + + ScreenPtr pScreen; + + REQUEST(xShapeMaskReq); + RegionPtr srcRgn; + + RegionPtr *destRgn; + + PixmapPtr pPixmap; + + CreateDftPtr createDefault; + + REQUEST_SIZE_MATCH(xShapeMaskReq); + UpdateCurrentTime(); + pWin = SecurityLookupWindow(stuff->dest, client, SecurityWriteAccess); + if (!pWin) + return BadWindow; + switch (stuff->destKind) { + case ShapeBounding: + createDefault = CreateBoundingShape; + break; + case ShapeClip: + createDefault = CreateClipShape; + break; + case ShapeInput: + createDefault = CreateBoundingShape; + break; + default: + client->errorValue = stuff->destKind; + return BadValue; + } + pScreen = pWin->drawable.pScreen; + if (stuff->src == None) + srcRgn = 0; + else { + pPixmap = (PixmapPtr) SecurityLookupIDByType(client, stuff->src, + RT_PIXMAP, + SecurityReadAccess); + if (!pPixmap) + return BadPixmap; + if (pPixmap->drawable.pScreen != pScreen || + pPixmap->drawable.depth != 1) + return BadMatch; + srcRgn = BITMAP_TO_REGION(pScreen, pPixmap); + if (!srcRgn) + return BadAlloc; + } + + if (!pWin->optional) + MakeWindowOptional(pWin); + switch (stuff->destKind) { + case ShapeBounding: + destRgn = &pWin->optional->boundingShape; + break; + case ShapeClip: + destRgn = &pWin->optional->clipShape; + break; + case ShapeInput: + destRgn = &pWin->optional->inputShape; + break; + default: + return BadValue; + } + + return RegionOperate(client, pWin, (int) stuff->destKind, + destRgn, srcRgn, (int) stuff->op, + stuff->xOff, stuff->yOff, createDefault); +} + + +/************ + * ProcShapeCombine + ************/ + +static int +ProcShapeCombine(client) +ClientPtr client; +{ + WindowPtr pSrcWin, pDestWin; + + ScreenPtr pScreen; + + REQUEST(xShapeCombineReq); + RegionPtr srcRgn; + + RegionPtr *destRgn; + + CreateDftPtr createDefault; + + CreateDftPtr createSrc; + + RegionPtr tmp; + + REQUEST_SIZE_MATCH(xShapeCombineReq); + UpdateCurrentTime(); + pDestWin = LookupWindow(stuff->dest, client); + if (!pDestWin) + return BadWindow; + if (!pDestWin->optional) + MakeWindowOptional(pDestWin); + switch (stuff->destKind) { + case ShapeBounding: + createDefault = CreateBoundingShape; + break; + case ShapeClip: + createDefault = CreateClipShape; + break; + case ShapeInput: + createDefault = CreateBoundingShape; + break; + default: + client->errorValue = stuff->destKind; + return BadValue; + } + pScreen = pDestWin->drawable.pScreen; + + pSrcWin = LookupWindow(stuff->src, client); + if (!pSrcWin) + return BadWindow; + switch (stuff->srcKind) { + case ShapeBounding: + srcRgn = wBoundingShape(pSrcWin); + createSrc = CreateBoundingShape; + break; + case ShapeClip: + srcRgn = wClipShape(pSrcWin); + createSrc = CreateClipShape; + break; + case ShapeInput: + srcRgn = wInputShape(pSrcWin); + createSrc = CreateBoundingShape; + break; + default: + client->errorValue = stuff->srcKind; + return BadValue; + } + if (pSrcWin->drawable.pScreen != pScreen) { + return BadMatch; + } + + if (srcRgn) { + tmp = REGION_CREATE((BoxPtr) 0, 0); + REGION_COPY(tmp, srcRgn); + srcRgn = tmp; + } + else + srcRgn = (*createSrc) (pSrcWin); + + if (!pDestWin->optional) + MakeWindowOptional(pDestWin); + switch (stuff->destKind) { + case ShapeBounding: + destRgn = &pDestWin->optional->boundingShape; + break; + case ShapeClip: + destRgn = &pDestWin->optional->clipShape; + break; + case ShapeInput: + destRgn = &pDestWin->optional->inputShape; + break; + default: + return BadValue; + } + + return RegionOperate(client, pDestWin, (int) stuff->destKind, + destRgn, srcRgn, (int) stuff->op, + stuff->xOff, stuff->yOff, createDefault); +} + + +/************* + * ProcShapeOffset + *************/ + +static int +ProcShapeOffset(client) +ClientPtr client; +{ + WindowPtr pWin; + + ScreenPtr pScreen; + + REQUEST(xShapeOffsetReq); + RegionPtr srcRgn; + + REQUEST_SIZE_MATCH(xShapeOffsetReq); + UpdateCurrentTime(); + pWin = LookupWindow(stuff->dest, client); + if (!pWin) + return BadWindow; + switch (stuff->destKind) { + case ShapeBounding: + srcRgn = wBoundingShape(pWin); + break; + case ShapeClip: + srcRgn = wClipShape(pWin); + break; + case ShapeInput: + srcRgn = wInputShape(pWin); + break; + default: + client->errorValue = stuff->destKind; + return BadValue; + } + pScreen = pWin->drawable.pScreen; + if (srcRgn) { + REGION_TRANSLATE(srcRgn, stuff->xOff, stuff->yOff); + (*pScreen->SetShape) (pWin); + } + SendShapeNotify(pWin, (int) stuff->destKind); + return Success; +} + + +static int +ProcShapeQueryExtents(client) +ClientPtr client; +{ + REQUEST(xShapeQueryExtentsReq); + WindowPtr pWin; + + xShapeQueryExtentsReply rep; + + BoxRec extents, *pExtents; + + RegionPtr region; + + REQUEST_SIZE_MATCH(xShapeQueryExtentsReq); + pWin = LookupWindow(stuff->window, client); + if (!pWin) + return BadWindow; + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.boundingShaped = (wBoundingShape(pWin) != 0); + rep.clipShaped = (wClipShape(pWin) != 0); + if ((region = wBoundingShape(pWin))) { + /* this is done in two steps because of a compiler bug on SunOS 4.1.3 */ + pExtents = REGION_EXTENTS(region); + extents = *pExtents; + } + else { + extents.x1 = -wBorderWidth(pWin); + extents.y1 = -wBorderWidth(pWin); + extents.x2 = pWin->drawable.width + wBorderWidth(pWin); + extents.y2 = pWin->drawable.height + wBorderWidth(pWin); + } + rep.xBoundingShape = extents.x1; + rep.yBoundingShape = extents.y1; + rep.widthBoundingShape = extents.x2 - extents.x1; + rep.heightBoundingShape = extents.y2 - extents.y1; + if ((region = wClipShape(pWin))) { + /* this is done in two steps because of a compiler bug on SunOS 4.1.3 */ + pExtents = REGION_EXTENTS(region); + extents = *pExtents; + } + else { + extents.x1 = 0; + extents.y1 = 0; + extents.x2 = pWin->drawable.width; + extents.y2 = pWin->drawable.height; + } + rep.xClipShape = extents.x1; + rep.yClipShape = extents.y1; + rep.widthClipShape = extents.x2 - extents.x1; + rep.heightClipShape = extents.y2 - extents.y1; + if (client->swapped) { + swaps(&rep.sequenceNumber); + swapl(&rep.length); + swaps(&rep.xBoundingShape); + swaps(&rep.yBoundingShape); + swaps(&rep.widthBoundingShape); + swaps(&rep.heightBoundingShape); + swaps(&rep.xClipShape); + swaps(&rep.yClipShape); + swaps(&rep.widthClipShape); + swaps(&rep.heightClipShape); + } + WriteToClient(client, sizeof(xShapeQueryExtentsReply), (char *) &rep); + return (client->noClientException); +} + + /*ARGSUSED*/ static int +ShapeFreeClient(data, id) +pointer data; + +XID id; +{ + ShapeEventPtr pShapeEvent; + + WindowPtr pWin; + + ShapeEventPtr *pHead, pCur, pPrev; + + pShapeEvent = (ShapeEventPtr) data; + pWin = pShapeEvent->window; + pHead = (ShapeEventPtr *) LookupIDByType(pWin->drawable.id, EventType); + if (pHead) { + pPrev = 0; + for (pCur = *pHead; pCur && pCur != pShapeEvent; pCur = pCur->next) + pPrev = pCur; + if (pCur) { + if (pPrev) + pPrev->next = pShapeEvent->next; + else + *pHead = pShapeEvent->next; + } + } + free((pointer) pShapeEvent); + return 1; +} + + /*ARGSUSED*/ static int +ShapeFreeEvents(data, id) +pointer data; + +XID id; +{ + ShapeEventPtr *pHead, pCur, pNext; + + pHead = (ShapeEventPtr *) data; + for (pCur = *pHead; pCur; pCur = pNext) { + pNext = pCur->next; + FreeResource(pCur->clientResource, ClientType); + free((pointer) pCur); + } + free((pointer) pHead); + return 1; +} + +static int +ProcShapeSelectInput(client) +ClientPtr client; +{ + REQUEST(xShapeSelectInputReq); + WindowPtr pWin; + + ShapeEventPtr pShapeEvent, pNewShapeEvent, *pHead; + + XID clientResource; + + REQUEST_SIZE_MATCH(xShapeSelectInputReq); + pWin = SecurityLookupWindow(stuff->window, client, SecurityWriteAccess); + if (!pWin) + return BadWindow; + pHead = (ShapeEventPtr *) SecurityLookupIDByType(client, + pWin->drawable.id, + EventType, + SecurityWriteAccess); + switch (stuff->enable) { + case xTrue: + if (pHead) { + + /* check for existing entry. */ + for (pShapeEvent = *pHead; + pShapeEvent; pShapeEvent = pShapeEvent->next) { + if (pShapeEvent->client == client) + return Success; + } + } + + /* build the entry */ + pNewShapeEvent = (ShapeEventPtr) + malloc(sizeof(ShapeEventRec)); + if (!pNewShapeEvent) + return BadAlloc; + pNewShapeEvent->next = 0; + pNewShapeEvent->client = client; + pNewShapeEvent->window = pWin; + /* + * add a resource that will be deleted when + * the client goes away + */ + clientResource = FakeClientID(client->index); + pNewShapeEvent->clientResource = clientResource; + if (!AddResource(clientResource, ClientType, (pointer) pNewShapeEvent)) + return BadAlloc; + /* + * create a resource to contain a pointer to the list + * of clients selecting input. This must be indirect as + * the list may be arbitrarily rearranged which cannot be + * done through the resource database. + */ + if (!pHead) { + pHead = malloc(sizeof(ShapeEventPtr)); + if (!pHead || + !AddResource(pWin->drawable.id, EventType, (pointer) pHead)) { + FreeResource(clientResource, RT_NONE); + return BadAlloc; + } + *pHead = 0; + } + pNewShapeEvent->next = *pHead; + *pHead = pNewShapeEvent; + break; + case xFalse: + /* delete the interest */ + if (pHead) { + pNewShapeEvent = 0; + for (pShapeEvent = *pHead; pShapeEvent; + pShapeEvent = pShapeEvent->next) { + if (pShapeEvent->client == client) + break; + pNewShapeEvent = pShapeEvent; + } + if (pShapeEvent) { + FreeResource(pShapeEvent->clientResource, ClientType); + if (pNewShapeEvent) + pNewShapeEvent->next = pShapeEvent->next; + else + *pHead = pShapeEvent->next; + free(pShapeEvent); + } + } + break; + default: + client->errorValue = stuff->enable; + return BadValue; + } + return Success; +} + +/* + * deliver the event + */ + +void +SendShapeNotify(pWin, which) +WindowPtr pWin; + +int which; +{ + ShapeEventPtr *pHead, pShapeEvent; + + ClientPtr client; + + xShapeNotifyEvent se; + + BoxRec extents; + + RegionPtr region; + + BYTE shaped; + + pHead = (ShapeEventPtr *) LookupIDByType(pWin->drawable.id, EventType); + if (!pHead) + return; + switch (which) { + case ShapeBounding: + region = wBoundingShape(pWin); + if (region) { + extents = *REGION_EXTENTS(region); + shaped = xTrue; + } + else { + extents.x1 = -wBorderWidth(pWin); + extents.y1 = -wBorderWidth(pWin); + extents.x2 = pWin->drawable.width + wBorderWidth(pWin); + extents.y2 = pWin->drawable.height + wBorderWidth(pWin); + shaped = xFalse; + } + break; + case ShapeClip: + region = wClipShape(pWin); + if (region) { + extents = *REGION_EXTENTS(region); + shaped = xTrue; + } + else { + extents.x1 = 0; + extents.y1 = 0; + extents.x2 = pWin->drawable.width; + extents.y2 = pWin->drawable.height; + shaped = xFalse; + } + break; + case ShapeInput: + region = wInputShape(pWin); + if (region) { + extents = *REGION_EXTENTS(region); + shaped = xTrue; + } + else { + extents.x1 = -wBorderWidth(pWin); + extents.y1 = -wBorderWidth(pWin); + extents.x2 = pWin->drawable.width + wBorderWidth(pWin); + extents.y2 = pWin->drawable.height + wBorderWidth(pWin); + shaped = xFalse; + } + break; + default: + return; + } + for (pShapeEvent = *pHead; pShapeEvent; pShapeEvent = pShapeEvent->next) { + client = pShapeEvent->client; + if (client == serverClient || client->clientGone) + continue; + se.type = ShapeNotify + ShapeEventBase; + se.kind = which; + se.window = pWin->drawable.id; + se.sequenceNumber = client->sequence; + se.x = extents.x1; + se.y = extents.y1; + se.width = extents.x2 - extents.x1; + se.height = extents.y2 - extents.y1; + se.time = currentTime.milliseconds; + se.shaped = shaped; + WriteEventsToClient(client, 1, (xEvent *) &se); + } +} + +static int +ProcShapeInputSelected(client) +ClientPtr client; +{ + REQUEST(xShapeInputSelectedReq); + WindowPtr pWin; + + ShapeEventPtr pShapeEvent, *pHead; + + int enabled; + + xShapeInputSelectedReply rep; + + REQUEST_SIZE_MATCH(xShapeInputSelectedReq); + pWin = LookupWindow(stuff->window, client); + if (!pWin) + return BadWindow; + pHead = (ShapeEventPtr *) SecurityLookupIDByType(client, + pWin->drawable.id, + EventType, + SecurityReadAccess); + enabled = xFalse; + if (pHead) { + for (pShapeEvent = *pHead; pShapeEvent; pShapeEvent = pShapeEvent->next) { + if (pShapeEvent->client == client) { + enabled = xTrue; + break; + } + } + } + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.enabled = enabled; + if (client->swapped) { + swaps(&rep.sequenceNumber); + swapl(&rep.length); + } + WriteToClient(client, sizeof(xShapeInputSelectedReply), (char *) &rep); + return (client->noClientException); +} + +static int +ProcShapeGetRectangles(client) +ClientPtr client; +{ + REQUEST(xShapeGetRectanglesReq); + WindowPtr pWin; + + xShapeGetRectanglesReply rep; + + xRectangle *rects; + + int nrects, i; + + RegionPtr region; + + REQUEST_SIZE_MATCH(xShapeGetRectanglesReq); + pWin = LookupWindow(stuff->window, client); + if (!pWin) + return BadWindow; + switch (stuff->kind) { + case ShapeBounding: + region = wBoundingShape(pWin); + break; + case ShapeClip: + region = wClipShape(pWin); + break; + case ShapeInput: + region = wInputShape(pWin); + break; + default: + client->errorValue = stuff->kind; + return BadValue; + } + if (!region) { + nrects = 1; + rects = (xRectangle *) ALLOCATE_LOCAL(sizeof(xRectangle)); + if (!rects) + return BadAlloc; + switch (stuff->kind) { + case ShapeBounding: + rects->x = -(int) wBorderWidth(pWin); + rects->y = -(int) wBorderWidth(pWin); + rects->width = pWin->drawable.width + wBorderWidth(pWin); + rects->height = pWin->drawable.height + wBorderWidth(pWin); + break; + case ShapeClip: + rects->x = 0; + rects->y = 0; + rects->width = pWin->drawable.width; + rects->height = pWin->drawable.height; + break; + case ShapeInput: + rects->x = -(int) wBorderWidth(pWin); + rects->y = -(int) wBorderWidth(pWin); + rects->width = pWin->drawable.width + wBorderWidth(pWin); + rects->height = pWin->drawable.height + wBorderWidth(pWin); + break; + } + } + else { + BoxPtr box; + + nrects = REGION_NUM_RECTS(region); + box = REGION_RECTS(region); + rects = (xRectangle *) ALLOCATE_LOCAL(nrects * sizeof(xRectangle)); + if (!rects && nrects) + return BadAlloc; + for (i = 0; i < nrects; i++, box++) { + rects[i].x = box->x1; + rects[i].y = box->y1; + rects[i].width = box->x2 - box->x1; + rects[i].height = box->y2 - box->y1; + } + } + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = (nrects * sizeof(xRectangle)) >> 2; + rep.ordering = YXBanded; + rep.nrects = nrects; + if (client->swapped) { + swaps(&rep.sequenceNumber); + swapl(&rep.length); + swapl(&rep.nrects); + SwapShorts((short *) rects, (unsigned long) nrects * 4); + } + WriteToClient(client, sizeof(rep), (char *) &rep); + WriteToClient(client, nrects * sizeof(xRectangle), (char *) rects); + DEALLOCATE_LOCAL(rects); + return client->noClientException; +} + +static int +ProcShapeDispatch(client) +ClientPtr client; +{ + REQUEST(xReq); + switch (stuff->data) { + case X_ShapeQueryVersion: + return ProcShapeQueryVersion(client); + case X_ShapeRectangles: + return ProcShapeRectangles(client); + case X_ShapeMask: + return ProcShapeMask(client); + case X_ShapeCombine: + return ProcShapeCombine(client); + case X_ShapeOffset: + return ProcShapeOffset(client); + case X_ShapeQueryExtents: + return ProcShapeQueryExtents(client); + case X_ShapeSelectInput: + return ProcShapeSelectInput(client); + case X_ShapeInputSelected: + return ProcShapeInputSelected(client); + case X_ShapeGetRectangles: + return ProcShapeGetRectangles(client); + default: + return BadRequest; + } +} + +static void +SShapeNotifyEvent(from, to) +xShapeNotifyEvent *from, *to; +{ + to->type = from->type; + to->kind = from->kind; + cpswapl(from->window, to->window); + cpswaps(from->sequenceNumber, to->sequenceNumber); + cpswaps(from->x, to->x); + cpswaps(from->y, to->y); + cpswaps(from->width, to->width); + cpswaps(from->height, to->height); + cpswapl(from->time, to->time); + to->shaped = from->shaped; +} + +static int +SProcShapeQueryVersion(client) +ClientPtr client; +{ + REQUEST(xShapeQueryVersionReq); + + swaps(&stuff->length); + return ProcShapeQueryVersion(client); +} + +static int +SProcShapeRectangles(client) +ClientPtr client; +{ + REQUEST(xShapeRectanglesReq); + + swaps(&stuff->length); + REQUEST_AT_LEAST_SIZE(xShapeRectanglesReq); + swapl(&stuff->dest); + swaps(&stuff->xOff); + swaps(&stuff->yOff); + SwapRestS(stuff); + return ProcShapeRectangles(client); +} + +static int +SProcShapeMask(client) +ClientPtr client; +{ + REQUEST(xShapeMaskReq); + + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xShapeMaskReq); + swapl(&stuff->dest); + swaps(&stuff->xOff); + swaps(&stuff->yOff); + swapl(&stuff->src); + return ProcShapeMask(client); +} + +static int +SProcShapeCombine(client) +ClientPtr client; +{ + REQUEST(xShapeCombineReq); + + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xShapeCombineReq); + swapl(&stuff->dest); + swaps(&stuff->xOff); + swaps(&stuff->yOff); + swapl(&stuff->src); + return ProcShapeCombine(client); +} + +static int +SProcShapeOffset(client) +ClientPtr client; +{ + REQUEST(xShapeOffsetReq); + + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xShapeOffsetReq); + swapl(&stuff->dest); + swaps(&stuff->xOff); + swaps(&stuff->yOff); + return ProcShapeOffset(client); +} + +static int +SProcShapeQueryExtents(client) +ClientPtr client; +{ + REQUEST(xShapeQueryExtentsReq); + + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xShapeQueryExtentsReq); + swapl(&stuff->window); + return ProcShapeQueryExtents(client); +} + +static int +SProcShapeSelectInput(client) +ClientPtr client; +{ + REQUEST(xShapeSelectInputReq); + + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xShapeSelectInputReq); + swapl(&stuff->window); + return ProcShapeSelectInput(client); +} + +static int +SProcShapeInputSelected(client) +ClientPtr client; +{ + REQUEST(xShapeInputSelectedReq); + + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xShapeInputSelectedReq); + swapl(&stuff->window); + return ProcShapeInputSelected(client); +} + +static int +SProcShapeGetRectangles(client) +ClientPtr client; +{ + REQUEST(xShapeGetRectanglesReq); + + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xShapeGetRectanglesReq); + swapl(&stuff->window); + return ProcShapeGetRectangles(client); +} + +static int +SProcShapeDispatch(client) +ClientPtr client; +{ + REQUEST(xReq); + switch (stuff->data) { + case X_ShapeQueryVersion: + return SProcShapeQueryVersion(client); + case X_ShapeRectangles: + return SProcShapeRectangles(client); + case X_ShapeMask: + return SProcShapeMask(client); + case X_ShapeCombine: + return SProcShapeCombine(client); + case X_ShapeOffset: + return SProcShapeOffset(client); + case X_ShapeQueryExtents: + return SProcShapeQueryExtents(client); + case X_ShapeSelectInput: + return SProcShapeSelectInput(client); + case X_ShapeInputSelected: + return SProcShapeInputSelected(client); + case X_ShapeGetRectangles: + return SProcShapeGetRectangles(client); + default: + return BadRequest; + } +} diff --git a/Xext/shm.c b/Xext/shm.c new file mode 100644 index 0000000..edb9701 --- /dev/null +++ b/Xext/shm.c @@ -0,0 +1,991 @@ +/************************************************************ + +Copyright 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. + +********************************************************/ + +/* THIS IS NOT AN X CONSORTIUM STANDARD OR AN X PROJECT TEAM SPECIFICATION */ + +#define SHM + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include "misc.h" +#include "os.h" +#include "dixstruct.h" +#include "resource.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "pixmapstr.h" +#include "gcstruct.h" +#include "extnsionst.h" +#include "servermd.h" +#define _XSHM_SERVER_ +#include +#include + + +#include "extinit.h" + +typedef struct _ShmDesc { + struct _ShmDesc *next; + int shmid; + int refcnt; + char *addr; + Bool writable; + unsigned long size; +} ShmDescRec, *ShmDescPtr; + +static void miShmPutImage(XSHM_PUT_IMAGE_ARGS); + +static void fbShmPutImage(XSHM_PUT_IMAGE_ARGS); + +static PixmapPtr fbShmCreatePixmap(XSHM_CREATE_PIXMAP_ARGS); + +static int ShmDetachSegment(pointer /* value */ , + XID /* shmseg */ + ); + +static void ShmResetProc(ExtensionEntry * /* extEntry */ + ); + +static void SShmCompletionEvent(xShmCompletionEvent * /* from */ , + xShmCompletionEvent * /* to */ + ); + +static Bool ShmDestroyPixmap(PixmapPtr pPixmap); + +static DISPATCH_PROC(ProcShmAttach); + +static DISPATCH_PROC(ProcShmCreatePixmap); + +static DISPATCH_PROC(ProcShmDetach); + +static DISPATCH_PROC(ProcShmDispatch); + +static DISPATCH_PROC(ProcShmGetImage); + +static DISPATCH_PROC(ProcShmPutImage); + +static DISPATCH_PROC(ProcShmQueryVersion); + +static DISPATCH_PROC(SProcShmAttach); + +static DISPATCH_PROC(SProcShmCreatePixmap); + +static DISPATCH_PROC(SProcShmDetach); + +static DISPATCH_PROC(SProcShmDispatch); + +static DISPATCH_PROC(SProcShmGetImage); + +static DISPATCH_PROC(SProcShmPutImage); + +static DISPATCH_PROC(SProcShmQueryVersion); + +static unsigned char ShmReqCode; + +_X_EXPORT int ShmCompletionCode; + +_X_EXPORT int BadShmSegCode; + +_X_EXPORT RESTYPE ShmSegType; + +static ShmDescPtr Shmsegs; + +static Bool sharedPixmaps; + +static int pixmapFormat; + +static int shmPixFormat[MAXSCREENS]; + +static const ShmFuncs * shmFuncs[MAXSCREENS]; + +static DestroyPixmapProcPtr destroyPixmap[MAXSCREENS]; + +static int shmPixmapPrivate; +static const ShmFuncs miFuncs = { NULL, miShmPutImage }; +static const ShmFuncs fbFuncs = { fbShmCreatePixmap, fbShmPutImage }; + +#define VERIFY_SHMSEG(shmseg,shmdesc,client) \ +{ \ + shmdesc = (ShmDescPtr)LookupIDByType(shmseg, ShmSegType); \ + if (!shmdesc) \ + { \ + client->errorValue = shmseg; \ + return BadShmSegCode; \ + } \ +} + +#define VERIFY_SHMPTR(shmseg,offset,needwrite,shmdesc,client) \ +{ \ + VERIFY_SHMSEG(shmseg, shmdesc, client); \ + if ((offset & 3) || (offset > shmdesc->size)) \ + { \ + client->errorValue = offset; \ + return BadValue; \ + } \ + if (needwrite && !shmdesc->writable) \ + return BadAccess; \ +} + +#define VERIFY_SHMSIZE(shmdesc,offset,len,client) \ +{ \ + if ((offset + len) > shmdesc->size) \ + { \ + return BadAccess; \ + } \ +} + +#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__CYGWIN__) +#include + +static Bool badSysCall = FALSE; + +static void +SigSysHandler(signo) +int signo; +{ + badSysCall = TRUE; +} + +static Bool +CheckForShmSyscall() +{ + void (*oldHandler) (); + + int shmid = -1; + + /* If no SHM support in the kernel, the bad syscall will generate SIGSYS */ + oldHandler = signal(SIGSYS, SigSysHandler); + + badSysCall = FALSE; + shmid = shmget(IPC_PRIVATE, 4096, IPC_CREAT); + + if (shmid != -1) { + /* Successful allocation - clean up */ + shmctl(shmid, IPC_RMID, (struct shmid_ds *) NULL); + } + else { + /* Allocation failed */ + badSysCall = TRUE; + } + signal(SIGSYS, oldHandler); + return (!badSysCall); +} + +#define MUST_CHECK_FOR_SHM_SYSCALL + +#endif + +void +ShmExtensionInit(INITARGS) +{ + ExtensionEntry *extEntry; + + int i; + +#ifdef MUST_CHECK_FOR_SHM_SYSCALL + if (!CheckForShmSyscall()) { + ErrorF("MIT-SHM extension disabled due to lack of kernel support\n"); + return; + } +#endif + + sharedPixmaps = xFalse; + pixmapFormat = 0; + { + sharedPixmaps = xTrue; + pixmapFormat = shmPixFormat[0]; + for (i = 0; i < screenInfo.numScreens; i++) { + if (!shmFuncs[i]) + shmFuncs[i] = &miFuncs; + if (!shmFuncs[i]->CreatePixmap) + sharedPixmaps = xFalse; + if (shmPixFormat[i] && (shmPixFormat[i] != pixmapFormat)) { + sharedPixmaps = xFalse; + pixmapFormat = 0; + } + } + if (!pixmapFormat) + pixmapFormat = ZPixmap; + if (sharedPixmaps) { + for (i = 0; i < screenInfo.numScreens; i++) { + destroyPixmap[i] = screenInfo.screens[i]->DestroyPixmap; + screenInfo.screens[i]->DestroyPixmap = ShmDestroyPixmap; + } + shmPixmapPrivate = AllocatePixmapPrivateIndex(); + for (i = 0; i < screenInfo.numScreens; i++) { + if (!AllocatePixmapPrivate(screenInfo.screens[i], + shmPixmapPrivate, 0)) + return; + } + } + } + ShmSegType = CreateNewResourceType(ShmDetachSegment); + if (ShmSegType && + (extEntry = AddExtension(SHMNAME, ShmNumberEvents, ShmNumberErrors, + ProcShmDispatch, SProcShmDispatch, + ShmResetProc, StandardMinorOpcode))) { + ShmReqCode = (unsigned char) extEntry->base; + ShmCompletionCode = extEntry->eventBase; + BadShmSegCode = extEntry->errorBase; + EventSwapVector[ShmCompletionCode] = (EventSwapPtr) SShmCompletionEvent; + } +} + + /*ARGSUSED*/ static void +ShmResetProc(extEntry) +ExtensionEntry *extEntry; +{ + int i; + + for (i = 0; i < MAXSCREENS; i++) { + shmFuncs[i] = (ShmFuncsPtr) NULL; + shmPixFormat[i] = 0; + } +} + +void +ShmRegisterFuncs(ScreenPtr pScreen, ShmFuncsPtr funcs) +{ + shmFuncs[pScreen->myNum] = funcs; +} + +void +ShmSetPixmapFormat(ScreenPtr pScreen, int format) +{ + shmPixFormat[pScreen->myNum] = format; +} + +static Bool +ShmDestroyPixmap(PixmapPtr pPixmap) +{ + ScreenPtr pScreen = pPixmap->drawable.pScreen; + + Bool ret; + + if (pPixmap->refcnt == 1) { + ShmDescPtr shmdesc; + + shmdesc = (ShmDescPtr) pPixmap->devPrivates[shmPixmapPrivate].ptr; + if (shmdesc) + ShmDetachSegment((pointer) shmdesc, pPixmap->drawable.id); + } + + pScreen->DestroyPixmap = destroyPixmap[pScreen->myNum]; + ret = (*pScreen->DestroyPixmap) (pPixmap); + destroyPixmap[pScreen->myNum] = pScreen->DestroyPixmap; + pScreen->DestroyPixmap = ShmDestroyPixmap; + return ret; +} + +void +ShmRegisterFbFuncs(pScreen) +ScreenPtr pScreen; +{ + shmFuncs[pScreen->myNum] = &fbFuncs; +} + +static int +ProcShmQueryVersion(client) +ClientPtr client; +{ + xShmQueryVersionReply rep; + + + REQUEST_SIZE_MATCH(xShmQueryVersionReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.sharedPixmaps = sharedPixmaps; + rep.pixmapFormat = pixmapFormat; + rep.majorVersion = SHM_MAJOR_VERSION; + rep.minorVersion = SHM_MINOR_VERSION; + rep.uid = geteuid(); + rep.gid = getegid(); + if (client->swapped) { + swaps(&rep.sequenceNumber); + swapl(&rep.length); + swaps(&rep.majorVersion); + swaps(&rep.minorVersion); + swaps(&rep.uid); + swaps(&rep.gid); + } + WriteToClient(client, sizeof(xShmQueryVersionReply), (char *) &rep); + return (client->noClientException); +} + +/* + * Simulate the access() system call for a shared memory segement, + * using the credentials from the client if available + */ +static int +shm_access(ClientPtr client, struct ipc_perm *perm, int readonly) +{ + int uid, gid; + + mode_t mask; + + if (LocalClientCred(client, &uid, &gid) != -1) { + + /* User id 0 always gets access */ + if (uid == 0) { + return 0; + } + /* Check the owner */ + if (perm->uid == uid || perm->cuid == uid) { + mask = S_IRUSR; + if (!readonly) { + mask |= S_IWUSR; + } + return (perm->mode & mask) == mask ? 0 : -1; + } + /* Check the group */ + if (perm->gid == gid || perm->cgid == gid) { + mask = S_IRGRP; + if (!readonly) { + mask |= S_IWGRP; + } + return (perm->mode & mask) == mask ? 0 : -1; + } + } + /* Otherwise, check everyone else */ + mask = S_IROTH; + if (!readonly) { + mask |= S_IWOTH; + } + return (perm->mode & mask) == mask ? 0 : -1; +} + +static int +ProcShmAttach(client) +ClientPtr client; +{ + struct shmid_ds buf; + + ShmDescPtr shmdesc; + + REQUEST(xShmAttachReq); + + REQUEST_SIZE_MATCH(xShmAttachReq); + LEGAL_NEW_RESOURCE(stuff->shmseg, client); + if ((stuff->readOnly != xTrue) && (stuff->readOnly != xFalse)) { + client->errorValue = stuff->readOnly; + return (BadValue); + } + for (shmdesc = Shmsegs; + shmdesc && (shmdesc->shmid != stuff->shmid); shmdesc = shmdesc->next); + if (shmdesc) { + if (!stuff->readOnly && !shmdesc->writable) + return BadAccess; + shmdesc->refcnt++; + } + else { + shmdesc = malloc(sizeof(ShmDescRec)); + if (!shmdesc) + return BadAlloc; + shmdesc->addr = shmat(stuff->shmid, 0, + stuff->readOnly ? SHM_RDONLY : 0); + if ((shmdesc->addr == ((char *) -1)) || + shmctl(stuff->shmid, IPC_STAT, &buf)) { + free(shmdesc); + return BadAccess; + } + + /* The attach was performed with root privs. We must + * do manual checking of access rights for the credentials + * of the client */ + + if (shm_access(client, &(buf.shm_perm), stuff->readOnly) == -1) { + shmdt(shmdesc->addr); + free(shmdesc); + return BadAccess; + } + + shmdesc->shmid = stuff->shmid; + shmdesc->refcnt = 1; + shmdesc->writable = !stuff->readOnly; + shmdesc->size = buf.shm_segsz; + shmdesc->next = Shmsegs; + Shmsegs = shmdesc; + } + if (!AddResource(stuff->shmseg, ShmSegType, (pointer) shmdesc)) + return BadAlloc; + return (client->noClientException); +} + + /*ARGSUSED*/ static int +ShmDetachSegment(value, shmseg) +pointer value; /* must conform to DeleteType */ + +XID shmseg; +{ + ShmDescPtr shmdesc = (ShmDescPtr) value; + + ShmDescPtr *prev; + + if (--shmdesc->refcnt) + return TRUE; + shmdt(shmdesc->addr); + for (prev = &Shmsegs; *prev != shmdesc; prev = &(*prev)->next); + *prev = shmdesc->next; + free(shmdesc); + return Success; +} + +static int +ProcShmDetach(client) +ClientPtr client; +{ + ShmDescPtr shmdesc; + + REQUEST(xShmDetachReq); + + REQUEST_SIZE_MATCH(xShmDetachReq); + VERIFY_SHMSEG(stuff->shmseg, shmdesc, client); + FreeResource(stuff->shmseg, RT_NONE); + return (client->noClientException); +} + +static void +miShmPutImage(dst, pGC, depth, format, w, h, sx, sy, sw, sh, dx, dy, data) +DrawablePtr dst; + +GCPtr pGC; + +int depth, w, h, sx, sy, sw, sh, dx, dy; + +unsigned int format; + +char *data; +{ + PixmapPtr pmap; + + GCPtr putGC; + + putGC = GetScratchGC(depth, dst->pScreen); + if (!putGC) + return; + pmap = (*dst->pScreen->CreatePixmap) (dst->pScreen, sw, sh, depth); + if (!pmap) { + FreeScratchGC(putGC); + return; + } + ValidateGC((DrawablePtr) pmap, putGC); + (*putGC->ops->PutImage) ((DrawablePtr) pmap, putGC, depth, -sx, -sy, w, h, + 0, (format == XYPixmap) ? XYPixmap : ZPixmap, + data); + FreeScratchGC(putGC); + if (format == XYBitmap) + (void) (*pGC->ops->CopyPlane) ((DrawablePtr) pmap, dst, pGC, 0, 0, sw, + sh, dx, dy, 1L); + else + (void) (*pGC->ops->CopyArea) ((DrawablePtr) pmap, dst, pGC, 0, 0, sw, + sh, dx, dy); + (*pmap->drawable.pScreen->DestroyPixmap) (pmap); +} + +static void +fbShmPutImage(dst, pGC, depth, format, w, h, sx, sy, sw, sh, dx, dy, data) +DrawablePtr dst; + +GCPtr pGC; + +int depth, w, h, sx, sy, sw, sh, dx, dy; + +unsigned int format; + +char *data; +{ + if ((format == ZPixmap) || (depth == 1)) { + PixmapPtr pPixmap; + + pPixmap = GetScratchPixmapHeader(dst->pScreen, w, h, depth, + BitsPerPixel(depth), PixmapBytePad(w, + depth), + (pointer) data); + if (!pPixmap) + return; + if (format == XYBitmap) + (void) (*pGC->ops->CopyPlane) ((DrawablePtr) pPixmap, dst, pGC, + sx, sy, sw, sh, dx, dy, 1L); + else + (void) (*pGC->ops->CopyArea) ((DrawablePtr) pPixmap, dst, pGC, + sx, sy, sw, sh, dx, dy); + FreeScratchPixmapHeader(pPixmap); + } + else + miShmPutImage(dst, pGC, depth, format, w, h, sx, sy, sw, sh, dx, dy, + data); +} + + +static int +ProcShmPutImage(client) +ClientPtr client; +{ + GCPtr pGC; + + DrawablePtr pDraw; + + long length; + + ShmDescPtr shmdesc; + + REQUEST(xShmPutImageReq); + + REQUEST_SIZE_MATCH(xShmPutImageReq); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + VERIFY_SHMPTR(stuff->shmseg, stuff->offset, FALSE, shmdesc, client); + if ((stuff->sendEvent != xTrue) && (stuff->sendEvent != xFalse)) + return BadValue; + if (stuff->format == XYBitmap) { + if (stuff->depth != 1) + return BadMatch; + length = PixmapBytePad(stuff->totalWidth, 1); + } + else if (stuff->format == XYPixmap) { + if (pDraw->depth != stuff->depth) + return BadMatch; + length = PixmapBytePad(stuff->totalWidth, 1); + length *= stuff->depth; + } + else if (stuff->format == ZPixmap) { + if (pDraw->depth != stuff->depth) + return BadMatch; + length = PixmapBytePad(stuff->totalWidth, stuff->depth); + } + else { + client->errorValue = stuff->format; + return BadValue; + } + + VERIFY_SHMSIZE(shmdesc, stuff->offset, length * stuff->totalHeight, client); + if (stuff->srcX > stuff->totalWidth) { + client->errorValue = stuff->srcX; + return BadValue; + } + if (stuff->srcY > stuff->totalHeight) { + client->errorValue = stuff->srcY; + return BadValue; + } + if ((stuff->srcX + stuff->srcWidth) > stuff->totalWidth) { + client->errorValue = stuff->srcWidth; + return BadValue; + } + if ((stuff->srcY + stuff->srcHeight) > stuff->totalHeight) { + client->errorValue = stuff->srcHeight; + return BadValue; + } + + if ((((stuff->format == ZPixmap) && (stuff->srcX == 0)) || + ((stuff->format != ZPixmap) && + (stuff->srcX < screenInfo.bitmapScanlinePad) && + ((stuff->format == XYBitmap) || + ((stuff->srcY == 0) && + (stuff->srcHeight == stuff->totalHeight))))) && + ((stuff->srcX + stuff->srcWidth) == stuff->totalWidth)) + (*pGC->ops->PutImage) (pDraw, pGC, stuff->depth, + stuff->dstX, stuff->dstY, + stuff->totalWidth, stuff->srcHeight, + stuff->srcX, stuff->format, + shmdesc->addr + stuff->offset + + (stuff->srcY * length)); + else + (*shmFuncs[pDraw->pScreen->myNum]->PutImage) (pDraw, pGC, stuff->depth, + stuff->format, + stuff->totalWidth, + stuff->totalHeight, + stuff->srcX, stuff->srcY, + stuff->srcWidth, + stuff->srcHeight, + stuff->dstX, stuff->dstY, + shmdesc->addr + + stuff->offset); + + if (stuff->sendEvent) { + xShmCompletionEvent ev; + + ev.type = ShmCompletionCode; + ev.drawable = stuff->drawable; + ev.sequenceNumber = client->sequence; + ev.minorEvent = X_ShmPutImage; + ev.majorEvent = ShmReqCode; + ev.shmseg = stuff->shmseg; + ev.offset = stuff->offset; + WriteEventsToClient(client, 1, (xEvent *) &ev); + } + + return (client->noClientException); +} + +static int +ProcShmGetImage(client) +ClientPtr client; +{ + DrawablePtr pDraw; + + long lenPer = 0, length; + + Mask plane = 0; + + xShmGetImageReply xgi; + + ShmDescPtr shmdesc; + + REQUEST(xShmGetImageReq); + + REQUEST_SIZE_MATCH(xShmGetImageReq); + if ((stuff->format != XYPixmap) && (stuff->format != ZPixmap)) { + client->errorValue = stuff->format; + return (BadValue); + } + VERIFY_DRAWABLE(pDraw, stuff->drawable, client); + VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client); + if (pDraw->type == DRAWABLE_WINDOW) { + if ( /* check for being viewable */ + !((WindowPtr) pDraw)->realized || + /* check for being on screen */ + pDraw->x + stuff->x < 0 || + pDraw->x + stuff->x + (int) stuff->width > pDraw->pScreen->width + || pDraw->y + stuff->y < 0 || + pDraw->y + stuff->y + (int) stuff->height > + pDraw->pScreen->height || + /* check for being inside of border */ + stuff->x < -wBorderWidth((WindowPtr) pDraw) || + stuff->x + (int) stuff->width > + wBorderWidth((WindowPtr) pDraw) + (int) pDraw->width || + stuff->y < -wBorderWidth((WindowPtr) pDraw) || + stuff->y + (int) stuff->height > + wBorderWidth((WindowPtr) pDraw) + (int) pDraw->height) + return (BadMatch); + xgi.visual = wVisual(((WindowPtr) pDraw)); + } + else { + if (stuff->x < 0 || + stuff->x + (int) stuff->width > pDraw->width || + stuff->y < 0 || stuff->y + (int) stuff->height > pDraw->height) + return (BadMatch); + xgi.visual = None; + } + xgi.type = X_Reply; + xgi.length = 0; + xgi.sequenceNumber = client->sequence; + xgi.depth = pDraw->depth; + if (stuff->format == ZPixmap) { + length = PixmapBytePad(stuff->width, pDraw->depth) * stuff->height; + } + else { + lenPer = PixmapBytePad(stuff->width, 1) * stuff->height; + plane = ((Mask) 1) << (pDraw->depth - 1); + /* only planes asked for */ + length = lenPer * Ones(stuff->planeMask & (plane | (plane - 1))); + } + + VERIFY_SHMSIZE(shmdesc, stuff->offset, length, client); + xgi.size = length; + + if (length == 0) { + /* nothing to do */ + } + else if (stuff->format == ZPixmap) { + (*pDraw->pScreen->GetImage) (pDraw, stuff->x, stuff->y, + stuff->width, stuff->height, + stuff->format, stuff->planeMask, + shmdesc->addr + stuff->offset); + } + else { + + length = stuff->offset; + for (; plane; plane >>= 1) { + if (stuff->planeMask & plane) { + (*pDraw->pScreen->GetImage) (pDraw, + stuff->x, stuff->y, + stuff->width, stuff->height, + stuff->format, plane, + shmdesc->addr + length); + length += lenPer; + } + } + } + + if (client->swapped) { + swaps(&xgi.sequenceNumber); + swapl(&xgi.length); + swapl(&xgi.visual); + swapl(&xgi.size); + } + WriteToClient(client, sizeof(xShmGetImageReply), (char *) &xgi); + + return (client->noClientException); +} + +static PixmapPtr +fbShmCreatePixmap(pScreen, width, height, depth, addr) +ScreenPtr pScreen; + +int width; + +int height; + +int depth; + +char *addr; +{ + PixmapPtr pPixmap; + + pPixmap = (*pScreen->CreatePixmap) (pScreen, 0, 0, pScreen->rootDepth); + if (!pPixmap) + return NullPixmap; + + if (!(*pScreen->ModifyPixmapHeader) (pPixmap, width, height, depth, + BitsPerPixel(depth), + PixmapBytePad(width, depth), + (pointer) addr)) { + (*pScreen->DestroyPixmap) (pPixmap); + return NullPixmap; + } + return pPixmap; +} + +static int +ProcShmCreatePixmap(client) +ClientPtr client; +{ + PixmapPtr pMap; + + DrawablePtr pDraw; + + DepthPtr pDepth; + + int i; + + ShmDescPtr shmdesc; + + REQUEST(xShmCreatePixmapReq); + + REQUEST_SIZE_MATCH(xShmCreatePixmapReq); + client->errorValue = stuff->pid; + if (!sharedPixmaps) + return BadImplementation; + LEGAL_NEW_RESOURCE(stuff->pid, client); + VERIFY_GEOMETRABLE(pDraw, stuff->drawable, client); + VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client); + if (!stuff->width || !stuff->height) { + client->errorValue = 0; + return BadValue; + } + 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: + VERIFY_SHMSIZE(shmdesc, stuff->offset, + PixmapBytePad(stuff->width, stuff->depth) * stuff->height, + client); + pMap = + (*shmFuncs[pDraw->pScreen->myNum]->CreatePixmap) (pDraw->pScreen, + stuff->width, + stuff->height, + stuff->depth, + shmdesc->addr + + stuff->offset); + if (pMap) { + pMap->devPrivates[shmPixmapPrivate].ptr = (pointer) shmdesc; + shmdesc->refcnt++; + pMap->drawable.serialNumber = NEXT_SERIAL_NUMBER; + pMap->drawable.id = stuff->pid; + if (AddResource(stuff->pid, RT_PIXMAP, (pointer) pMap)) { + return (client->noClientException); + } + } + return (BadAlloc); +} + +static int +ProcShmDispatch(client) +ClientPtr client; +{ + REQUEST(xReq); + switch (stuff->data) { + case X_ShmQueryVersion: + return ProcShmQueryVersion(client); + case X_ShmAttach: + return ProcShmAttach(client); + case X_ShmDetach: + return ProcShmDetach(client); + case X_ShmPutImage: + return ProcShmPutImage(client); + case X_ShmGetImage: + return ProcShmGetImage(client); + case X_ShmCreatePixmap: + return ProcShmCreatePixmap(client); + default: + return BadRequest; + } +} + +static void +SShmCompletionEvent(from, to) +xShmCompletionEvent *from, *to; +{ + to->type = from->type; + cpswaps(from->sequenceNumber, to->sequenceNumber); + cpswapl(from->drawable, to->drawable); + cpswaps(from->minorEvent, to->minorEvent); + to->majorEvent = from->majorEvent; + cpswapl(from->shmseg, to->shmseg); + cpswapl(from->offset, to->offset); +} + +static int +SProcShmQueryVersion(client) +ClientPtr client; +{ + + REQUEST(xShmQueryVersionReq); + + swaps(&stuff->length); + return ProcShmQueryVersion(client); +} + +static int +SProcShmAttach(client) +ClientPtr client; +{ + + REQUEST(xShmAttachReq); + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xShmAttachReq); + swapl(&stuff->shmseg); + swapl(&stuff->shmid); + return ProcShmAttach(client); +} + +static int +SProcShmDetach(client) +ClientPtr client; +{ + + REQUEST(xShmDetachReq); + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xShmDetachReq); + swapl(&stuff->shmseg); + return ProcShmDetach(client); +} + +static int +SProcShmPutImage(client) +ClientPtr client; +{ + + REQUEST(xShmPutImageReq); + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xShmPutImageReq); + swapl(&stuff->drawable); + swapl(&stuff->gc); + swaps(&stuff->totalWidth); + swaps(&stuff->totalHeight); + swaps(&stuff->srcX); + swaps(&stuff->srcY); + swaps(&stuff->srcWidth); + swaps(&stuff->srcHeight); + swaps(&stuff->dstX); + swaps(&stuff->dstY); + swapl(&stuff->shmseg); + swapl(&stuff->offset); + return ProcShmPutImage(client); +} + +static int +SProcShmGetImage(client) +ClientPtr client; +{ + + REQUEST(xShmGetImageReq); + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xShmGetImageReq); + swapl(&stuff->drawable); + swaps(&stuff->x); + swaps(&stuff->y); + swaps(&stuff->width); + swaps(&stuff->height); + swapl(&stuff->planeMask); + swapl(&stuff->shmseg); + swapl(&stuff->offset); + return ProcShmGetImage(client); +} + +static int +SProcShmCreatePixmap(client) +ClientPtr client; +{ + + REQUEST(xShmCreatePixmapReq); + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xShmCreatePixmapReq); + swapl(&stuff->pid); + swapl(&stuff->drawable); + swaps(&stuff->width); + swaps(&stuff->height); + swapl(&stuff->shmseg); + swapl(&stuff->offset); + return ProcShmCreatePixmap(client); +} + +static int +SProcShmDispatch(client) +ClientPtr client; +{ + REQUEST(xReq); + switch (stuff->data) { + case X_ShmQueryVersion: + return SProcShmQueryVersion(client); + case X_ShmAttach: + return SProcShmAttach(client); + case X_ShmDetach: + return SProcShmDetach(client); + case X_ShmPutImage: + return SProcShmPutImage(client); + case X_ShmGetImage: + return SProcShmGetImage(client); + case X_ShmCreatePixmap: + return SProcShmCreatePixmap(client); + default: + return BadRequest; + } +} diff --git a/Xext/shmint.h b/Xext/shmint.h new file mode 100644 index 0000000..0b5367e --- /dev/null +++ b/Xext/shmint.h @@ -0,0 +1,43 @@ +/* + * + * Copyright © 2003 Keith Packard + * + * 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, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _SHMINT_H_ +#define _SHMINT_H_ + +#define _XSHM_SERVER_ +#include + +#include "screenint.h" +#include "pixmap.h" +#include "gc.h" + +void + ShmRegisterFuncs(ScreenPtr pScreen, ShmFuncsPtr funcs); + +void + ShmSetPixmapFormat(ScreenPtr pScreen, int format); + +void + ShmRegisterFbFuncs(ScreenPtr pScreen); + +#endif /* _SHMINT_H_ */ diff --git a/Xext/sleepuntil.c b/Xext/sleepuntil.c new file mode 100644 index 0000000..5952614 --- /dev/null +++ b/Xext/sleepuntil.c @@ -0,0 +1,240 @@ +/* + * +Copyright 1992, 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. + * + * Author: Keith Packard, MIT X Consortium + */ + +/* dixsleep.c - implement millisecond timeouts for X clients */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "sleepuntil.h" +#include +#include +#include "misc.h" +#include "windowstr.h" +#include "dixstruct.h" +#include "pixmapstr.h" +#include "scrnintstr.h" + +typedef struct _Sertafied { + struct _Sertafied *next; + TimeStamp revive; + ClientPtr pClient; + XID id; + void (*notifyFunc) (ClientPtr /* client */ , + pointer /* closure */ + ); + + pointer closure; +} SertafiedRec, *SertafiedPtr; + +static SertafiedPtr pPending; + +static RESTYPE SertafiedResType; + +static Bool BlockHandlerRegistered; + +static int SertafiedGeneration; + +static void ClientAwaken(ClientPtr /* client */ , + pointer /* closure */ + ); + +static int SertafiedDelete(pointer /* value */ , + XID /* id */ + ); + +static void SertafiedBlockHandler(pointer /* data */ , + OSTimePtr /* wt */ , + pointer /* LastSelectMask */ + ); + +static void SertafiedWakeupHandler(pointer /* data */ , + int /* i */ , + pointer /* LastSelectMask */ + ); + +_X_EXPORT int +ClientSleepUntil(client, revive, notifyFunc, closure) +ClientPtr client; + +TimeStamp *revive; + +void (*notifyFunc) (ClientPtr /* client */ , + pointer /* closure */ ); + +pointer closure; +{ + SertafiedPtr pRequest, pReq, pPrev; + + if (SertafiedGeneration != serverGeneration) { + SertafiedResType = CreateNewResourceType(SertafiedDelete); + if (!SertafiedResType) + return FALSE; + SertafiedGeneration = serverGeneration; + BlockHandlerRegistered = FALSE; + } + pRequest = malloc(sizeof(SertafiedRec)); + if (!pRequest) + return FALSE; + pRequest->pClient = client; + pRequest->revive = *revive; + pRequest->id = FakeClientID(client->index); + pRequest->closure = closure; + if (!BlockHandlerRegistered) { + if (!RegisterBlockAndWakeupHandlers(SertafiedBlockHandler, + SertafiedWakeupHandler, + (pointer) 0)) { + free(pRequest); + return FALSE; + } + BlockHandlerRegistered = TRUE; + } + pRequest->notifyFunc = 0; + if (!AddResource(pRequest->id, SertafiedResType, (pointer) pRequest)) + return FALSE; + if (!notifyFunc) + notifyFunc = ClientAwaken; + pRequest->notifyFunc = notifyFunc; + /* Insert into time-ordered queue, with earliest activation time coming first. */ + pPrev = 0; + for (pReq = pPending; pReq; pReq = pReq->next) { + if (CompareTimeStamps(pReq->revive, *revive) == LATER) + break; + pPrev = pReq; + } + if (pPrev) + pPrev->next = pRequest; + else + pPending = pRequest; + pRequest->next = pReq; + IgnoreClient(client); + return TRUE; +} + +static void +ClientAwaken(client, closure) +ClientPtr client; + +pointer closure; +{ + if (!client->clientGone) + AttendClient(client); +} + +static int +SertafiedDelete(value, id) +pointer value; + +XID id; +{ + SertafiedPtr pRequest = (SertafiedPtr) value; + + SertafiedPtr pReq, pPrev; + + pPrev = 0; + for (pReq = pPending; pReq; pPrev = pReq, pReq = pReq->next) + if (pReq == pRequest) { + if (pPrev) + pPrev->next = pReq->next; + else + pPending = pReq->next; + break; + } + if (pRequest->notifyFunc) + (*pRequest->notifyFunc) (pRequest->pClient, pRequest->closure); + free(pRequest); + return TRUE; +} + +static void +SertafiedBlockHandler(data, wt, LastSelectMask) +pointer data; /* unused */ + +OSTimePtr wt; /* wait time */ + +pointer LastSelectMask; +{ + SertafiedPtr pReq, pNext; + + unsigned long delay; + + TimeStamp now; + + if (!pPending) + return; + now.milliseconds = GetTimeInMillis(); + now.months = currentTime.months; + if ((int) (now.milliseconds - currentTime.milliseconds) < 0) + now.months++; + for (pReq = pPending; pReq; pReq = pNext) { + pNext = pReq->next; + if (CompareTimeStamps(pReq->revive, now) == LATER) + break; + FreeResource(pReq->id, RT_NONE); + + /* AttendClient() may have been called via the resource delete + * function so a client may have input to be processed and so + * set delay to 0 to prevent blocking in WaitForSomething(). + */ + AdjustWaitForDelay(wt, 0); + } + pReq = pPending; + if (!pReq) + return; + delay = pReq->revive.milliseconds - now.milliseconds; + AdjustWaitForDelay(wt, delay); +} + +static void +SertafiedWakeupHandler(data, i, LastSelectMask) +pointer data; + +int i; + +pointer LastSelectMask; +{ + SertafiedPtr pReq, pNext; + + TimeStamp now; + + now.milliseconds = GetTimeInMillis(); + now.months = currentTime.months; + if ((int) (now.milliseconds - currentTime.milliseconds) < 0) + now.months++; + for (pReq = pPending; pReq; pReq = pNext) { + pNext = pReq->next; + if (CompareTimeStamps(pReq->revive, now) == LATER) + break; + FreeResource(pReq->id, RT_NONE); + } + if (!pPending) { + RemoveBlockAndWakeupHandlers(SertafiedBlockHandler, + SertafiedWakeupHandler, (pointer) 0); + BlockHandlerRegistered = FALSE; + } +} diff --git a/Xext/sleepuntil.h b/Xext/sleepuntil.h new file mode 100644 index 0000000..5c70848 --- /dev/null +++ b/Xext/sleepuntil.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2001 The XFree86 Project, 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, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * 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 + * XFREE86 PROJECT 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 XFree86 Project 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 + * XFree86 Project. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#ifndef _SLEEPUNTIL_H_ +#define _SLEEPUNTIL_H_ 1 + +#include "dix.h" + +extern int ClientSleepUntil(ClientPtr client, + TimeStamp *revive, + void (*notifyFunc) (ClientPtr /* client */ , + pointer /* closure */ + ), pointer Closure); + +#endif diff --git a/Xext/sync.c b/Xext/sync.c new file mode 100644 index 0000000..88ad5e6 --- /dev/null +++ b/Xext/sync.c @@ -0,0 +1,2456 @@ +/* + +Copyright 1991, 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. + +Copyright 1991, 1993 by Digital Equipment Corporation, Maynard, Massachusetts, +and Olivetti Research Limited, Cambridge, England. + + 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 names of Digital or Olivetti +not be used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. Digital and Olivetti +make no representations about the suitability of this software +for any purpose. It is provided "as is" without express or implied warranty. + +DIGITAL AND OLIVETTI DISCLAIM ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS, IN NO EVENT SHALL THEY BE LIABLE FOR ANY SPECIAL, INDIRECT OR +CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF +USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. + +*/ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include + +#include +#include +#include +#include "misc.h" +#include "os.h" +#include "extnsionst.h" +#include "dixstruct.h" +#include "resource.h" +#include "opaque.h" +#define _SYNC_SERVER +#include +#include + +#include +#include + +#include "extinit.h" + +/* + * Local Global Variables + */ +static int SyncEventBase; + +static int SyncErrorBase; + +static RESTYPE RTCounter = 0; + +static RESTYPE RTAwait; + +static RESTYPE RTAlarm; + +static RESTYPE RTAlarmClient; + +static int SyncNumSystemCounters = 0; + +static SyncCounter **SysCounterList = NULL; + +#define IsSystemCounter(pCounter) \ + (pCounter && (pCounter->client == NULL)) + +/* these are all the alarm attributes that pertain to the alarm's trigger */ +#define XSyncCAAllTrigger \ + (XSyncCACounter | XSyncCAValueType | XSyncCAValue | XSyncCATestType) + +static int + FreeAlarm(pointer /* addr */ , + XID /* id */ + ); + +static int + FreeAlarmClient(pointer /* value */ , + XID /* id */ + ); + +static int + FreeAwait(pointer /* addr */ , + XID /* id */ + ); + +static void + ServertimeBracketValues(pointer /* pCounter */ , + CARD64 * /* pbracket_less */ , + CARD64 * /* pbracket_greater */ + ); + +static void + ServertimeQueryValue(pointer /* pCounter */ , + CARD64 * /* pValue_return */ + ); + +static void + ServertimeWakeupHandler(pointer /* env */ , + int /* rc */ , + pointer /* LastSelectMask */ + ); + +static int + SyncInitTrigger(ClientPtr /* client */ , + SyncTrigger * /* pTrigger */ , + XSyncCounter /* counter */ , + Mask /* changes */ + ); + +static void + SAlarmNotifyEvent(xSyncAlarmNotifyEvent * /* from */ , + xSyncAlarmNotifyEvent * /* to */ + ); + +static void + SCounterNotifyEvent(xSyncCounterNotifyEvent * /* from */ , + xSyncCounterNotifyEvent * /* to */ + ); + +static void + ServertimeBlockHandler(pointer /* env */ , + struct timeval ** /* wt */ , + pointer /* LastSelectMask */ + ); + +static int + SyncAddTriggerToCounter(SyncTrigger * /* pTrigger */ + ); + +extern void + SyncAlarmCounterDestroyed(SyncTrigger * /* pTrigger */ + ); + +static void + SyncAlarmTriggerFired(SyncTrigger * /* pTrigger */ + ); + +static void + SyncAwaitTriggerFired(SyncTrigger * /* pTrigger */ + ); + +static int + SyncChangeAlarmAttributes(ClientPtr /* client */ , + SyncAlarm * /* pAlarm */ , + Mask /* mask */ , + CARD32 * /* values */ + ); + +static Bool + SyncCheckTriggerNegativeComparison(SyncTrigger * /* pTrigger */ , + CARD64 /* oldval */ + ); + +static Bool + SyncCheckTriggerNegativeTransition(SyncTrigger * /* pTrigger */ , + CARD64 /* oldval */ + ); + +static Bool + SyncCheckTriggerPositiveComparison(SyncTrigger * /* pTrigger */ , + CARD64 /* oldval */ + ); + +static Bool + SyncCheckTriggerPositiveTransition(SyncTrigger * /* pTrigger */ , + CARD64 /* oldval */ + ); + +static SyncCounter *SyncCreateCounter(ClientPtr /* client */ , + XSyncCounter /* id */ , + CARD64 /* initialvalue */ + ); + +static void SyncComputeBracketValues(SyncCounter * /* pCounter */ , + Bool /* startOver */ + ); + +static void + SyncDeleteTriggerFromCounter(SyncTrigger * /* pTrigger */ + ); + +static Bool + SyncEventSelectForAlarm(SyncAlarm * /* pAlarm */ , + ClientPtr /* client */ , + Bool /* wantevents */ + ); + +static void + SyncInitServerTime(void + ); + +static void + SyncResetProc(ExtensionEntry * /* extEntry */ + ); + +static void + SyncSendAlarmNotifyEvents(SyncAlarm * /* pAlarm */ + ); + +static void + SyncSendCounterNotifyEvents(ClientPtr /* client */ , + SyncAwait ** /* ppAwait */ , + int /* num_events */ + ); + +static DISPATCH_PROC(ProcSyncAwait); + +static DISPATCH_PROC(ProcSyncChangeAlarm); + +static DISPATCH_PROC(ProcSyncChangeCounter); + +static DISPATCH_PROC(ProcSyncCreateAlarm); + +static DISPATCH_PROC(ProcSyncCreateCounter); + +static DISPATCH_PROC(ProcSyncDestroyAlarm); + +static DISPATCH_PROC(ProcSyncDestroyCounter); + +static DISPATCH_PROC(ProcSyncDispatch); + +static DISPATCH_PROC(ProcSyncGetPriority); + +static DISPATCH_PROC(ProcSyncInitialize); + +static DISPATCH_PROC(ProcSyncListSystemCounters); + +static DISPATCH_PROC(ProcSyncQueryAlarm); + +static DISPATCH_PROC(ProcSyncQueryCounter); + +static DISPATCH_PROC(ProcSyncSetCounter); + +static DISPATCH_PROC(ProcSyncSetPriority); + +static DISPATCH_PROC(SProcSyncAwait); + +static DISPATCH_PROC(SProcSyncChangeAlarm); + +static DISPATCH_PROC(SProcSyncChangeCounter); + +static DISPATCH_PROC(SProcSyncCreateAlarm); + +static DISPATCH_PROC(SProcSyncCreateCounter); + +static DISPATCH_PROC(SProcSyncDestroyAlarm); + +static DISPATCH_PROC(SProcSyncDestroyCounter); + +static DISPATCH_PROC(SProcSyncDispatch); + +static DISPATCH_PROC(SProcSyncGetPriority); + +static DISPATCH_PROC(SProcSyncInitialize); + +static DISPATCH_PROC(SProcSyncListSystemCounters); + +static DISPATCH_PROC(SProcSyncQueryAlarm); + +static DISPATCH_PROC(SProcSyncQueryCounter); + +static DISPATCH_PROC(SProcSyncSetCounter); + +static DISPATCH_PROC(SProcSyncSetPriority); + +/* Each counter maintains a simple linked list of triggers that are + * interested in the counter. The two functions below are used to + * delete and add triggers on this list. + */ +static void +SyncDeleteTriggerFromCounter(pTrigger) +SyncTrigger *pTrigger; +{ + SyncTriggerList *pCur; + + SyncTriggerList *pPrev; + + /* pCounter needs to be stored in pTrigger before calling here. */ + + if (!pTrigger->pCounter) + return; + + pPrev = NULL; + pCur = pTrigger->pCounter->pTriglist; + + while (pCur) { + if (pCur->pTrigger == pTrigger) { + if (pPrev) + pPrev->next = pCur->next; + else + pTrigger->pCounter->pTriglist = pCur->next; + + free(pCur); + break; + } + + pPrev = pCur; + pCur = pCur->next; + } + + if (IsSystemCounter(pTrigger->pCounter)) + SyncComputeBracketValues(pTrigger->pCounter, /*startOver */ TRUE); +} + +static int +SyncAddTriggerToCounter(pTrigger) +SyncTrigger *pTrigger; +{ + SyncTriggerList *pCur; + + if (!pTrigger->pCounter) + return Success; + + /* don't do anything if it's already there */ + for (pCur = pTrigger->pCounter->pTriglist; pCur; pCur = pCur->next) { + if (pCur->pTrigger == pTrigger) + return Success; + } + + if (!(pCur = malloc(sizeof(SyncTriggerList)))) + return BadAlloc; + + pCur->pTrigger = pTrigger; + pCur->next = pTrigger->pCounter->pTriglist; + pTrigger->pCounter->pTriglist = pCur; + + if (IsSystemCounter(pTrigger->pCounter)) + SyncComputeBracketValues(pTrigger->pCounter, /*startOver */ TRUE); + + return Success; +} + +/* Below are four possible functions that can be plugged into + * pTrigger->CheckTrigger, corresponding to the four possible + * test-types. These functions are called after the counter's + * value changes but are also passed the old counter value + * so they can inspect both the old and new values. + * (PositiveTransition and NegativeTransition need to see both + * pieces of information.) These functions return the truth value + * of the trigger. + * + * All of them include the condition pTrigger->pCounter == NULL. + * This is because the spec says that a trigger with a counter value + * of None is always TRUE. + */ + +static Bool +SyncCheckTriggerPositiveComparison(pTrigger, oldval) +SyncTrigger *pTrigger; + +CARD64 oldval; +{ + return (pTrigger->pCounter == NULL || + XSyncValueGreaterOrEqual(pTrigger->pCounter->value, + pTrigger->test_value)); +} + +static Bool +SyncCheckTriggerNegativeComparison(pTrigger, oldval) +SyncTrigger *pTrigger; + +CARD64 oldval; +{ + return (pTrigger->pCounter == NULL || + XSyncValueLessOrEqual(pTrigger->pCounter->value, + pTrigger->test_value)); +} + +static Bool +SyncCheckTriggerPositiveTransition(pTrigger, oldval) +SyncTrigger *pTrigger; + +CARD64 oldval; +{ + return (pTrigger->pCounter == NULL || + (XSyncValueLessThan(oldval, pTrigger->test_value) && + XSyncValueGreaterOrEqual(pTrigger->pCounter->value, + pTrigger->test_value))); +} + +static Bool +SyncCheckTriggerNegativeTransition(pTrigger, oldval) +SyncTrigger *pTrigger; + +CARD64 oldval; +{ + return (pTrigger->pCounter == NULL || + (XSyncValueGreaterThan(oldval, pTrigger->test_value) && + XSyncValueLessOrEqual(pTrigger->pCounter->value, + pTrigger->test_value))); +} + +static int +SyncInitTrigger(client, pTrigger, counter, changes) +ClientPtr client; /* so we can set errorValue */ + +SyncTrigger *pTrigger; + +XSyncCounter counter; + +Mask changes; +{ + SyncCounter *pCounter = pTrigger->pCounter; + + int status; + + Bool newcounter = FALSE; + + if (changes & XSyncCACounter) { + if (counter == None) + pCounter = NULL; + else if (! + (pCounter = + (SyncCounter *) SecurityLookupIDByType(client, counter, + RTCounter, + SecurityReadAccess))) { + client->errorValue = counter; + return SyncErrorBase + XSyncBadCounter; + } + if (pCounter != pTrigger->pCounter) { /* new counter for trigger */ + SyncDeleteTriggerFromCounter(pTrigger); + pTrigger->pCounter = pCounter; + newcounter = TRUE; + } + } + + /* if system counter, ask it what the current value is */ + + if (IsSystemCounter(pCounter)) { + (*pCounter->pSysCounterInfo->QueryValue) ((pointer) pCounter, + &pCounter->value); + } + + if (changes & XSyncCAValueType) { + if (pTrigger->value_type != XSyncRelative && + pTrigger->value_type != XSyncAbsolute) { + client->errorValue = pTrigger->value_type; + return BadValue; + } + } + + if (changes & XSyncCATestType) { + if (pTrigger->test_type != XSyncPositiveTransition && + pTrigger->test_type != XSyncNegativeTransition && + pTrigger->test_type != XSyncPositiveComparison && + pTrigger->test_type != XSyncNegativeComparison) { + client->errorValue = pTrigger->test_type; + return BadValue; + } + /* select appropriate CheckTrigger function */ + + switch (pTrigger->test_type) { + case XSyncPositiveTransition: + pTrigger->CheckTrigger = SyncCheckTriggerPositiveTransition; + break; + case XSyncNegativeTransition: + pTrigger->CheckTrigger = SyncCheckTriggerNegativeTransition; + break; + case XSyncPositiveComparison: + pTrigger->CheckTrigger = SyncCheckTriggerPositiveComparison; + break; + case XSyncNegativeComparison: + pTrigger->CheckTrigger = SyncCheckTriggerNegativeComparison; + break; + } + } + + if (changes & (XSyncCAValueType | XSyncCAValue)) { + if (pTrigger->value_type == XSyncAbsolute) + pTrigger->test_value = pTrigger->wait_value; + else { /* relative */ + + Bool overflow; + + if (pCounter == NULL) + return BadMatch; + + XSyncValueAdd(&pTrigger->test_value, pCounter->value, + pTrigger->wait_value, &overflow); + if (overflow) { + client->errorValue = XSyncValueHigh32(pTrigger->wait_value); + return BadValue; + } + } + } + + /* we wait until we're sure there are no errors before registering + * a new counter on a trigger + */ + if (newcounter) { + if ((status = SyncAddTriggerToCounter(pTrigger)) != Success) + return status; + } + else if (IsSystemCounter(pCounter)) { + SyncComputeBracketValues(pCounter, /*startOver */ TRUE); + } + + return Success; +} + +/* AlarmNotify events happen in response to actions taken on an Alarm or + * the counter used by the alarm. AlarmNotify may be sent to multiple + * clients. The alarm maintains a list of clients interested in events. + */ +static void +SyncSendAlarmNotifyEvents(pAlarm) +SyncAlarm *pAlarm; +{ + SyncAlarmClientList *pcl; + + xSyncAlarmNotifyEvent ane; + + SyncTrigger *pTrigger = &pAlarm->trigger; + + UpdateCurrentTime(); + + ane.type = SyncEventBase + XSyncAlarmNotify; + ane.kind = XSyncAlarmNotify; + ane.sequenceNumber = pAlarm->client->sequence; + ane.alarm = pAlarm->alarm_id; + if (pTrigger->pCounter) { + ane.counter_value_hi = XSyncValueHigh32(pTrigger->pCounter->value); + ane.counter_value_lo = XSyncValueLow32(pTrigger->pCounter->value); + } + else { /* XXX what else can we do if there's no counter? */ + ane.counter_value_hi = ane.counter_value_lo = 0; + } + + ane.alarm_value_hi = XSyncValueHigh32(pTrigger->test_value); + ane.alarm_value_lo = XSyncValueLow32(pTrigger->test_value); + ane.time = currentTime.milliseconds; + ane.state = pAlarm->state; + + /* send to owner */ + if (pAlarm->events && !pAlarm->client->clientGone) + WriteEventsToClient(pAlarm->client, 1, (xEvent *) &ane); + + /* send to other interested clients */ + for (pcl = pAlarm->pEventClients; pcl; pcl = pcl->next) { + if (!pAlarm->client->clientGone) { + ane.sequenceNumber = pcl->client->sequence; + WriteEventsToClient(pcl->client, 1, (xEvent *) &ane); + } + } +} + +/* CounterNotify events only occur in response to an Await. The events + * go only to the Awaiting client. + */ +static void +SyncSendCounterNotifyEvents(client, ppAwait, num_events) +ClientPtr client; + +SyncAwait **ppAwait; + +int num_events; +{ + xSyncCounterNotifyEvent *pEvents, *pev; + + int i; + + if (client->clientGone) + return; + pev = pEvents = (xSyncCounterNotifyEvent *) + ALLOCATE_LOCAL(num_events * sizeof(xSyncCounterNotifyEvent)); + if (!pEvents) + return; + UpdateCurrentTime(); + for (i = 0; i < num_events; i++, ppAwait++, pev++) { + SyncTrigger *pTrigger = &(*ppAwait)->trigger; + + pev->type = SyncEventBase + XSyncCounterNotify; + pev->kind = XSyncCounterNotify; + pev->sequenceNumber = client->sequence; + pev->counter = pTrigger->pCounter->id; + pev->wait_value_lo = XSyncValueLow32(pTrigger->test_value); + pev->wait_value_hi = XSyncValueHigh32(pTrigger->test_value); + pev->counter_value_lo = XSyncValueLow32(pTrigger->pCounter->value); + pev->counter_value_hi = XSyncValueHigh32(pTrigger->pCounter->value); + pev->time = currentTime.milliseconds; + pev->count = num_events - i - 1; /* events remaining */ + pev->destroyed = pTrigger->pCounter->beingDestroyed; + } + /* swapping will be taken care of by this */ + WriteEventsToClient(client, num_events, (xEvent *) pEvents); + DEALLOCATE_LOCAL(pEvents); +} + +/* This function is called when an alarm's counter is destroyed. + * It is plugged into pTrigger->CounterDestroyed (for alarm triggers). + */ +void +SyncAlarmCounterDestroyed(pTrigger) +SyncTrigger *pTrigger; +{ + SyncAlarm *pAlarm = (SyncAlarm *) pTrigger; + + pAlarm->state = XSyncAlarmInactive; + SyncSendAlarmNotifyEvents(pAlarm); + pTrigger->pCounter = NULL; +} + +/* This function is called when an alarm "goes off." + * It is plugged into pTrigger->TriggerFired (for alarm triggers). + */ +static void +SyncAlarmTriggerFired(pTrigger) +SyncTrigger *pTrigger; +{ + SyncAlarm *pAlarm = (SyncAlarm *) pTrigger; + + CARD64 new_test_value; + + /* no need to check alarm unless it's active */ + if (pAlarm->state != XSyncAlarmActive) + return; + + /* " if the counter value is None, or if the delta is 0 and + * the test-type is PositiveComparison or NegativeComparison, + * no change is made to value (test-value) and the alarm + * state is changed to Inactive before the event is generated." + */ + if (pAlarm->trigger.pCounter == NULL || (XSyncValueIsZero(pAlarm->delta) + && (pAlarm->trigger.test_type == + XSyncPositiveComparison || + pAlarm->trigger.test_type == + XSyncNegativeComparison))) + pAlarm->state = XSyncAlarmInactive; + + new_test_value = pAlarm->trigger.test_value; + + if (pAlarm->state == XSyncAlarmActive) { + Bool overflow; + + CARD64 oldvalue; + + SyncTrigger *paTrigger = &pAlarm->trigger; + + /* "The alarm is updated by repeatedly adding delta to the + * value of the trigger and re-initializing it until it + * becomes FALSE." + */ + oldvalue = paTrigger->test_value; + + /* XXX really should do something smarter here */ + + do { + XSyncValueAdd(&paTrigger->test_value, paTrigger->test_value, + pAlarm->delta, &overflow); + } while (!overflow && + (*paTrigger->CheckTrigger) (paTrigger, + paTrigger->pCounter->value)); + + new_test_value = paTrigger->test_value; + paTrigger->test_value = oldvalue; + + /* "If this update would cause value to fall outside the range + * for an INT64...no change is made to value (test-value) and + * the alarm state is changed to Inactive before the event is + * generated." + */ + if (overflow) { + new_test_value = oldvalue; + pAlarm->state = XSyncAlarmInactive; + } + } + /* The AlarmNotify event has to have the "new state of the alarm" + * which we can't be sure of until this point. However, it has + * to have the "old" trigger test value. That's the reason for + * all the newvalue/oldvalue shuffling above. After we send the + * events, give the trigger its new test value. + */ + SyncSendAlarmNotifyEvents(pAlarm); + pTrigger->test_value = new_test_value; +} + +/* This function is called when an Await unblocks, either as a result + * of the trigger firing OR the counter being destroyed. + * It goes into pTrigger->TriggerFired AND pTrigger->CounterDestroyed + * (for Await triggers). + */ +static void +SyncAwaitTriggerFired(pTrigger) +SyncTrigger *pTrigger; +{ + SyncAwait *pAwait = (SyncAwait *) pTrigger; + + int numwaits; + + SyncAwaitUnion *pAwaitUnion; + + SyncAwait **ppAwait; + + int num_events = 0; + + pAwaitUnion = (SyncAwaitUnion *) pAwait->pHeader; + numwaits = pAwaitUnion->header.num_waitconditions; + ppAwait = (SyncAwait **) ALLOCATE_LOCAL(numwaits * sizeof(SyncAwait *)); + if (!ppAwait) + goto bail; + + pAwait = &(pAwaitUnion + 1)->await; + + /* "When a client is unblocked, all the CounterNotify events for + * the Await request are generated contiguously. If count is 0 + * there are no more events to follow for this request. If + * count is n, there are at least n more events to follow." + * + * Thus, it is best to find all the counters for which events + * need to be sent first, so that an accurate count field can + * be stored in the events. + */ + for (; numwaits; numwaits--, pAwait++) { + CARD64 diff; + + Bool overflow, diffgreater, diffequal; + + /* "A CounterNotify event with the destroyed flag set to TRUE is + * always generated if the counter for one of the triggers is + * destroyed." + */ + if (pAwait->trigger.pCounter->beingDestroyed) { + ppAwait[num_events++] = pAwait; + continue; + } + + /* "The difference between the counter and the test value is + * calculated by subtracting the test value from the value of + * the counter." + */ + XSyncValueSubtract(&diff, pAwait->trigger.pCounter->value, + pAwait->trigger.test_value, &overflow); + + /* "If the difference lies outside the range for an INT64, an + * event is not generated." + */ + if (overflow) + continue; + diffgreater = XSyncValueGreaterThan(diff, pAwait->event_threshold); + diffequal = XSyncValueEqual(diff, pAwait->event_threshold); + + /* "If the test-type is PositiveTransition or + * PositiveComparison, a CounterNotify event is generated if + * the difference is at least event-threshold. If the test-type + * is NegativeTransition or NegativeComparison, a CounterNotify + * event is generated if the difference is at most + * event-threshold." + */ + + if (((pAwait->trigger.test_type == XSyncPositiveComparison || + pAwait->trigger.test_type == XSyncPositiveTransition) + && (diffgreater || diffequal)) + || + ((pAwait->trigger.test_type == XSyncNegativeComparison || + pAwait->trigger.test_type == XSyncNegativeTransition) + && (!diffgreater) /* less or equal */ + ) + ) { + ppAwait[num_events++] = pAwait; + } + } + if (num_events) + SyncSendCounterNotifyEvents(pAwaitUnion->header.client, ppAwait, + num_events); + DEALLOCATE_LOCAL(ppAwait); + + bail: + /* unblock the client */ + AttendClient(pAwaitUnion->header.client); + /* delete the await */ + FreeResource(pAwaitUnion->header.delete_id, RT_NONE); +} + +/* This function should always be used to change a counter's value so that + * any triggers depending on the counter will be checked. + */ +void +SyncChangeCounter(pCounter, newval) +SyncCounter *pCounter; + +CARD64 newval; +{ + SyncTriggerList *ptl, *pnext; + + CARD64 oldval; + + oldval = pCounter->value; + pCounter->value = newval; + + /* run through triggers to see if any become true */ + for (ptl = pCounter->pTriglist; ptl; ptl = pnext) { + pnext = ptl->next; + if ((*ptl->pTrigger->CheckTrigger) (ptl->pTrigger, oldval)) + (*ptl->pTrigger->TriggerFired) (ptl->pTrigger); + } + + if (IsSystemCounter(pCounter)) { + SyncComputeBracketValues(pCounter, /* startOver */ FALSE); + } +} + +/* loosely based on dix/events.c/EventSelectForWindow */ +static Bool +SyncEventSelectForAlarm(pAlarm, client, wantevents) +SyncAlarm *pAlarm; + +ClientPtr client; + +Bool wantevents; +{ + SyncAlarmClientList *pClients; + + if (client == pAlarm->client) { /* alarm owner */ + pAlarm->events = wantevents; + return Success; + } + + /* see if the client is already on the list (has events selected) */ + + for (pClients = pAlarm->pEventClients; pClients; pClients = pClients->next) { + if (pClients->client == client) { + /* client's presence on the list indicates desire for + * events. If the client doesn't want events, remove it + * from the list. If the client does want events, do + * nothing, since it's already got them. + */ + if (!wantevents) { + FreeResource(pClients->delete_id, RT_NONE); + } + return Success; + } + } + + /* if we get here, this client does not currently have + * events selected on the alarm + */ + + if (!wantevents) + /* client doesn't want events, and we just discovered that it + * doesn't have them, so there's nothing to do. + */ + return Success; + + /* add new client to pAlarm->pEventClients */ + + pClients = malloc(sizeof(SyncAlarmClientList)); + if (!pClients) + return BadAlloc; + + /* register it as a resource so it will be cleaned up + * if the client dies + */ + + pClients->delete_id = FakeClientID(client->index); + if (!AddResource(pClients->delete_id, RTAlarmClient, pAlarm)) { + free(pClients); + return BadAlloc; + } + + /* link it into list after we know all the allocations succeed */ + + pClients->next = pAlarm->pEventClients; + pAlarm->pEventClients = pClients; + pClients->client = client; + return Success; +} + +/* + * ** SyncChangeAlarmAttributes ** This is used by CreateAlarm and ChangeAlarm + */ +static int +SyncChangeAlarmAttributes(client, pAlarm, mask, values) +ClientPtr client; + +SyncAlarm *pAlarm; + +Mask mask; + +CARD32 *values; +{ + int status; + + XSyncCounter counter; + + Mask origmask = mask; + + counter = pAlarm->trigger.pCounter ? pAlarm->trigger.pCounter->id : None; + + while (mask) { + int index2 = lowbit(mask); + + mask &= ~index2; + switch (index2) { + case XSyncCACounter: + mask &= ~XSyncCACounter; + /* sanity check in SyncInitTrigger */ + counter = *values++; + break; + + case XSyncCAValueType: + mask &= ~XSyncCAValueType; + /* sanity check in SyncInitTrigger */ + pAlarm->trigger.value_type = *values++; + break; + + case XSyncCAValue: + mask &= ~XSyncCAValue; + XSyncIntsToValue(&pAlarm->trigger.wait_value, values[1], values[0]); + values += 2; + break; + + case XSyncCATestType: + mask &= ~XSyncCATestType; + /* sanity check in SyncInitTrigger */ + pAlarm->trigger.test_type = *values++; + break; + + case XSyncCADelta: + mask &= ~XSyncCADelta; + XSyncIntsToValue(&pAlarm->delta, values[1], values[0]); + values += 2; + break; + + case XSyncCAEvents: + mask &= ~XSyncCAEvents; + if ((*values != xTrue) && (*values != xFalse)) { + client->errorValue = *values; + return BadValue; + } + status = SyncEventSelectForAlarm(pAlarm, client, + (Bool) (*values++)); + if (status != Success) + return status; + break; + + default: + client->errorValue = mask; + return BadValue; + } + } + + /* "If the test-type is PositiveComparison or PositiveTransition + * and delta is less than zero, or if the test-type is + * NegativeComparison or NegativeTransition and delta is + * greater than zero, a Match error is generated." + */ + if (origmask & (XSyncCADelta | XSyncCATestType)) { + CARD64 zero; + + XSyncIntToValue(&zero, 0); + if ((((pAlarm->trigger.test_type == XSyncPositiveComparison) || + (pAlarm->trigger.test_type == XSyncPositiveTransition)) + && XSyncValueLessThan(pAlarm->delta, zero)) + || + (((pAlarm->trigger.test_type == XSyncNegativeComparison) || + (pAlarm->trigger.test_type == XSyncNegativeTransition)) + && XSyncValueGreaterThan(pAlarm->delta, zero)) + ) { + return BadMatch; + } + } + + /* postpone this until now, when we're sure nothing else can go wrong */ + if ((status = SyncInitTrigger(client, &pAlarm->trigger, counter, + origmask & XSyncCAAllTrigger)) != Success) + return status; + + /* XXX spec does not really say to do this - needs clarification */ + pAlarm->state = XSyncAlarmActive; + return Success; +} + +static SyncCounter * +SyncCreateCounter(client, id, initialvalue) +ClientPtr client; + +XSyncCounter id; + +CARD64 initialvalue; +{ + SyncCounter *pCounter; + + if (!(pCounter = malloc(sizeof(SyncCounter)))) + return (SyncCounter *) NULL; + + if (!AddResource(id, RTCounter, (pointer) pCounter)) { + free((pointer) pCounter); + return (SyncCounter *) NULL; + } + + pCounter->client = client; + pCounter->id = id; + pCounter->value = initialvalue; + pCounter->pTriglist = NULL; + pCounter->beingDestroyed = FALSE; + pCounter->pSysCounterInfo = NULL; + return pCounter; +} + +static int FreeCounter(pointer /*env */ , + XID /*id */ + ); + +/* + * ***** System Counter utilities + */ + +pointer +SyncCreateSystemCounter(name, initial, resolution, counterType, + QueryValue, BracketValues) +char *name; + +CARD64 initial; + +CARD64 resolution; + +SyncCounterType counterType; + +void (*QueryValue) (pointer /* pCounter */ , + CARD64 * /* pValue_return */ ); + +void (*BracketValues) (pointer /* pCounter */ , + CARD64 * /* pbracket_less */ , + CARD64 * /* pbracket_greater */ ); +{ + SyncCounter *pCounter; + + SysCounterList = (SyncCounter **) realloc(SysCounterList, + (SyncNumSystemCounters + + 1) * sizeof(SyncCounter *)); + if (!SysCounterList) + return (pointer) NULL; + + /* this function may be called before SYNC has been initialized, so we + * have to make sure RTCounter is created. + */ + if (RTCounter == 0) { + RTCounter = CreateNewResourceType(FreeCounter); + if (RTCounter == 0) { + return (pointer) NULL; + } + } + + pCounter = SyncCreateCounter((ClientPtr) NULL, FakeClientID(0), initial); + + if (pCounter) { + SysCounterInfo *psci; + + psci = malloc(sizeof(SysCounterInfo)); + if (!psci) { + FreeResource(pCounter->id, RT_NONE); + return (pointer) pCounter; + } + pCounter->pSysCounterInfo = psci; + psci->name = name; + psci->resolution = resolution; + psci->counterType = counterType; + psci->QueryValue = QueryValue; + psci->BracketValues = BracketValues; + XSyncMaxValue(&psci->bracket_greater); + XSyncMinValue(&psci->bracket_less); + SysCounterList[SyncNumSystemCounters++] = pCounter; + } + return (pointer) pCounter; +} + +static void +SyncComputeBracketValues(pCounter, startOver) +SyncCounter *pCounter; + +Bool startOver; +{ + SyncTriggerList *pCur; + + SyncTrigger *pTrigger; + + SysCounterInfo *psci; + + CARD64 *pnewgtval = NULL; + + CARD64 *pnewltval = NULL; + + SyncCounterType ct; + + if (!pCounter) + return; + + psci = pCounter->pSysCounterInfo; + ct = pCounter->pSysCounterInfo->counterType; + if (ct == XSyncCounterNeverChanges) + return; + + if (startOver) { + XSyncMaxValue(&psci->bracket_greater); + XSyncMinValue(&psci->bracket_less); + } + + for (pCur = pCounter->pTriglist; pCur; pCur = pCur->next) { + pTrigger = pCur->pTrigger; + + if (pTrigger->test_type == XSyncPositiveComparison && + ct != XSyncCounterNeverIncreases) { + if (XSyncValueLessThan(pCounter->value, pTrigger->test_value) && + XSyncValueLessThan(pTrigger->test_value, + psci->bracket_greater)) { + psci->bracket_greater = pTrigger->test_value; + pnewgtval = &psci->bracket_greater; + } + } + else if (pTrigger->test_type == XSyncNegativeComparison && + ct != XSyncCounterNeverDecreases) { + if (XSyncValueGreaterThan(pCounter->value, pTrigger->test_value) && + XSyncValueGreaterThan(pTrigger->test_value, + psci->bracket_less)) { + psci->bracket_less = pTrigger->test_value; + pnewltval = &psci->bracket_less; + } + } + else if ((pTrigger->test_type == XSyncPositiveTransition && + ct != XSyncCounterNeverIncreases) + || + (pTrigger->test_type == XSyncNegativeTransition && + ct != XSyncCounterNeverDecreases) + ) { + if (XSyncValueLessThan(pCounter->value, pTrigger->test_value)) { + if (XSyncValueLessThan(pTrigger->test_value, + psci->bracket_greater)) { + psci->bracket_greater = pTrigger->test_value; + pnewgtval = &psci->bracket_greater; + } + else if (XSyncValueGreaterThan(pTrigger->test_value, + psci->bracket_less)) { + psci->bracket_less = pTrigger->test_value; + pnewltval = &psci->bracket_less; + } + } + } + } /* end for each trigger */ + + if (pnewgtval || pnewltval) { + (*psci->BracketValues) ((pointer) pCounter, pnewltval, pnewgtval); + } +} + +/* + * ***** Resource delete functions + */ + +/* ARGSUSED */ +static int +FreeAlarm(addr, id) +pointer addr; + +XID id; +{ + SyncAlarm *pAlarm = (SyncAlarm *) addr; + + pAlarm->state = XSyncAlarmDestroyed; + + SyncSendAlarmNotifyEvents(pAlarm); + + /* delete event selections */ + + while (pAlarm->pEventClients) + FreeResource(pAlarm->pEventClients->delete_id, RT_NONE); + + SyncDeleteTriggerFromCounter(&pAlarm->trigger); + + free(pAlarm); + return Success; +} + +/* + * ** Cleanup after the destruction of a Counter + */ +/* ARGSUSED */ +static int +FreeCounter(env, id) +pointer env; + +XID id; +{ + SyncCounter *pCounter = (SyncCounter *) env; + + SyncTriggerList *ptl, *pnext; + + pCounter->beingDestroyed = TRUE; + /* tell all the counter's triggers that the counter has been destroyed */ + for (ptl = pCounter->pTriglist; ptl; ptl = pnext) { + (*ptl->pTrigger->CounterDestroyed) (ptl->pTrigger); + pnext = ptl->next; + free(ptl); /* destroy the trigger list as we go */ + } + if (IsSystemCounter(pCounter)) { + int i, found = 0; + + free(pCounter->pSysCounterInfo); + + /* find the counter in the list of system counters and remove it */ + + if (SysCounterList) { + for (i = 0; i < SyncNumSystemCounters; i++) { + if (SysCounterList[i] == pCounter) { + found = i; + break; + } + } + if (found < (SyncNumSystemCounters - 1)) { + for (i = found; i < SyncNumSystemCounters - 1; i++) { + SysCounterList[i] = SysCounterList[i + 1]; + } + } + } + SyncNumSystemCounters--; + } + free(pCounter); + return Success; +} + +/* + * ** Cleanup after Await + */ +/* ARGSUSED */ +static int +FreeAwait(addr, id) +pointer addr; + +XID id; +{ + SyncAwaitUnion *pAwaitUnion = (SyncAwaitUnion *) addr; + + SyncAwait *pAwait; + + int numwaits; + + pAwait = &(pAwaitUnion + 1)->await; /* first await on list */ + + /* remove triggers from counters */ + + for (numwaits = pAwaitUnion->header.num_waitconditions; numwaits; + numwaits--, pAwait++) { + /* If the counter is being destroyed, FreeCounter will delete + * the trigger list itself, so don't do it here. + */ + SyncCounter *pCounter = pAwait->trigger.pCounter; + + if (pCounter && !pCounter->beingDestroyed) + SyncDeleteTriggerFromCounter(&pAwait->trigger); + } + free(pAwaitUnion); + return Success; +} + +/* loosely based on dix/events.c/OtherClientGone */ +static int +FreeAlarmClient(value, id) +pointer value; /* must conform to DeleteType */ + +XID id; +{ + SyncAlarm *pAlarm = (SyncAlarm *) value; + + SyncAlarmClientList *pCur, *pPrev; + + for (pPrev = NULL, pCur = pAlarm->pEventClients; + pCur; pPrev = pCur, pCur = pCur->next) { + if (pCur->delete_id == id) { + if (pPrev) + pPrev->next = pCur->next; + else + pAlarm->pEventClients = pCur->next; + free(pCur); + return (Success); + } + } + FatalError("alarm client not on event list"); + /*NOTREACHED*/} + +/* + * ***** Proc functions + */ + +/* + * ** Initialize the extension + */ +static int +ProcSyncInitialize(client) +ClientPtr client; +{ + xSyncInitializeReply rep; + + REQUEST_SIZE_MATCH(xSyncInitializeReq); + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.majorVersion = SYNC_MAJOR_VERSION; + rep.minorVersion = SYNC_MINOR_VERSION; + rep.length = 0; + + if (client->swapped) { + swaps(&rep.sequenceNumber); + } + WriteToClient(client, sizeof(rep), (char *) &rep); + return (client->noClientException); +} + +/* + * ** Get list of system counters available through the extension + */ +static int +ProcSyncListSystemCounters(client) +ClientPtr client; +{ + xSyncListSystemCountersReply rep; + + int i, len; + + xSyncSystemCounter *list = NULL, *walklist = NULL; + + REQUEST_SIZE_MATCH(xSyncListSystemCountersReq); + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.nCounters = SyncNumSystemCounters; + + for (i = len = 0; i < SyncNumSystemCounters; i++) { + char *name = SysCounterList[i]->pSysCounterInfo->name; + + /* pad to 4 byte boundary */ + len += (sz_xSyncSystemCounter + strlen(name) + 3) & ~3; + } + + if (len) { + walklist = list = (xSyncSystemCounter *) ALLOCATE_LOCAL(len); + if (!list) + return BadAlloc; + } + + rep.length = len >> 2; + + if (client->swapped) { + + swaps(&rep.sequenceNumber); + swapl(&rep.length); + swapl(&rep.nCounters); + } + + for (i = 0; i < SyncNumSystemCounters; i++) { + int namelen; + + char *pname_in_reply; + + SysCounterInfo *psci = SysCounterList[i]->pSysCounterInfo; + + walklist->counter = SysCounterList[i]->id; + walklist->resolution_hi = XSyncValueHigh32(psci->resolution); + walklist->resolution_lo = XSyncValueLow32(psci->resolution); + namelen = strlen(psci->name); + walklist->name_length = namelen; + + if (client->swapped) { + + swapl(&walklist->counter); + swapl(&walklist->resolution_hi); + swapl(&walklist->resolution_lo); + swaps(&walklist->name_length); + } + + pname_in_reply = ((char *) walklist) + sz_xSyncSystemCounter; + strncpy(pname_in_reply, psci->name, namelen); + walklist = (xSyncSystemCounter *) (((char *) walklist) + + ((sz_xSyncSystemCounter + namelen + + 3) & ~3)); + } + + WriteToClient(client, sizeof(rep), (char *) &rep); + if (len) { + WriteToClient(client, len, (char *) list); + DEALLOCATE_LOCAL(list); + } + + return (client->noClientException); +} + +/* + * ** Set client Priority + */ +static int +ProcSyncSetPriority(client) +ClientPtr client; +{ + REQUEST(xSyncSetPriorityReq); + ClientPtr priorityclient; + + REQUEST_SIZE_MATCH(xSyncSetPriorityReq); + + if (stuff->id == None) + priorityclient = client; + else if (!(priorityclient = LookupClient(stuff->id, client))) { + client->errorValue = stuff->id; + return BadMatch; + } + + if (priorityclient->priority != stuff->priority) { + priorityclient->priority = stuff->priority; + + /* The following will force the server back into WaitForSomething + * so that the change in this client's priority is immediately + * reflected. + */ + isItTimeToYield = TRUE; + dispatchException |= DE_PRIORITYCHANGE; + } + return Success; +} + +/* + * ** Get client Priority + */ +static int +ProcSyncGetPriority(client) +ClientPtr client; +{ + REQUEST(xSyncGetPriorityReq); + xSyncGetPriorityReply rep; + + ClientPtr priorityclient; + + REQUEST_SIZE_MATCH(xSyncGetPriorityReq); + + if (stuff->id == None) + priorityclient = client; + else if (!(priorityclient = LookupClient(stuff->id, client))) { + client->errorValue = stuff->id; + return BadMatch; + } + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.priority = priorityclient->priority; + + if (client->swapped) { + + swaps(&rep.sequenceNumber); + swapl(&rep.priority); + } + + WriteToClient(client, sizeof(xSyncGetPriorityReply), (char *) &rep); + + return (client->noClientException); +} + +/* + * ** Create a new counter + */ +static int +ProcSyncCreateCounter(client) +ClientPtr client; +{ + REQUEST(xSyncCreateCounterReq); + CARD64 initial; + + REQUEST_SIZE_MATCH(xSyncCreateCounterReq); + + LEGAL_NEW_RESOURCE(stuff->cid, client); + + XSyncIntsToValue(&initial, stuff->initial_value_lo, + stuff->initial_value_hi); + if (!SyncCreateCounter(client, stuff->cid, initial)) + return BadAlloc; + + return (client->noClientException); +} + +/* + * ** Set Counter value + */ +static int +ProcSyncSetCounter(client) +ClientPtr client; +{ + REQUEST(xSyncSetCounterReq); + SyncCounter *pCounter; + + CARD64 newvalue; + + REQUEST_SIZE_MATCH(xSyncSetCounterReq); + + pCounter = (SyncCounter *) SecurityLookupIDByType(client, stuff->cid, + RTCounter, + SecurityWriteAccess); + if (pCounter == NULL) { + client->errorValue = stuff->cid; + return SyncErrorBase + XSyncBadCounter; + } + + if (IsSystemCounter(pCounter)) { + client->errorValue = stuff->cid; + return BadAccess; + } + + XSyncIntsToValue(&newvalue, stuff->value_lo, stuff->value_hi); + SyncChangeCounter(pCounter, newvalue); + return Success; +} + +/* + * ** Change Counter value + */ +static int +ProcSyncChangeCounter(client) +ClientPtr client; +{ + REQUEST(xSyncChangeCounterReq); + SyncCounter *pCounter; + + CARD64 newvalue; + + Bool overflow; + + REQUEST_SIZE_MATCH(xSyncChangeCounterReq); + + pCounter = (SyncCounter *) SecurityLookupIDByType(client, stuff->cid, + RTCounter, + SecurityWriteAccess); + if (pCounter == NULL) { + client->errorValue = stuff->cid; + return SyncErrorBase + XSyncBadCounter; + } + + if (IsSystemCounter(pCounter)) { + client->errorValue = stuff->cid; + return BadAccess; + } + + XSyncIntsToValue(&newvalue, stuff->value_lo, stuff->value_hi); + XSyncValueAdd(&newvalue, pCounter->value, newvalue, &overflow); + if (overflow) { + /* XXX 64 bit value can't fit in 32 bits; do the best we can */ + client->errorValue = stuff->value_hi; + return BadValue; + } + SyncChangeCounter(pCounter, newvalue); + return Success; +} + +/* + * ** Destroy a counter + */ +static int +ProcSyncDestroyCounter(client) +ClientPtr client; +{ + REQUEST(xSyncDestroyCounterReq); + SyncCounter *pCounter; + + REQUEST_SIZE_MATCH(xSyncDestroyCounterReq); + + pCounter = (SyncCounter *) SecurityLookupIDByType(client, stuff->counter, + RTCounter, + SecurityDestroyAccess); + if (pCounter == NULL) { + client->errorValue = stuff->counter; + return SyncErrorBase + XSyncBadCounter; + } + if (IsSystemCounter(pCounter)) { + client->errorValue = stuff->counter; + return BadAccess; + } + FreeResource(pCounter->id, RT_NONE); + return Success; +} + +/* + * ** Await + */ +static int +ProcSyncAwait(client) +ClientPtr client; +{ + REQUEST(xSyncAwaitReq); + int len, items; + + int i; + + xSyncWaitCondition *pProtocolWaitConds; + + SyncAwaitUnion *pAwaitUnion; + + SyncAwait *pAwait; + + int status; + + REQUEST_AT_LEAST_SIZE(xSyncAwaitReq); + + len = client->req_len << 2; + len -= sz_xSyncAwaitReq; + items = len / sz_xSyncWaitCondition; + + if (items * sz_xSyncWaitCondition != len) { + return BadLength; + } + if (items == 0) { + client->errorValue = items; /* XXX protocol change */ + return BadValue; + } + + pProtocolWaitConds = (xSyncWaitCondition *) & stuff[1]; + + /* all the memory for the entire await list is allocated + * here in one chunk + */ + pAwaitUnion = + malloc((items + 1) * sizeof(SyncAwaitUnion)); + if (!pAwaitUnion) + return BadAlloc; + + /* first item is the header, remainder are real wait conditions */ + + pAwaitUnion->header.delete_id = FakeClientID(client->index); + if (!AddResource(pAwaitUnion->header.delete_id, RTAwait, pAwaitUnion)) { + free(pAwaitUnion); + return BadAlloc; + } + + /* don't need to do any more memory allocation for this request! */ + + pAwaitUnion->header.client = client; + pAwaitUnion->header.num_waitconditions = 0; + + pAwait = &(pAwaitUnion + 1)->await; /* skip over header */ + for (i = 0; i < items; i++, pProtocolWaitConds++, pAwait++) { + if (pProtocolWaitConds->counter == None) { /* XXX protocol change */ + /* this should take care of removing any triggers created by + * this request that have already been registered on counters + */ + FreeResource(pAwaitUnion->header.delete_id, RT_NONE); + client->errorValue = pProtocolWaitConds->counter; + return SyncErrorBase + XSyncBadCounter; + } + + /* sanity checks are in SyncInitTrigger */ + pAwait->trigger.pCounter = NULL; + pAwait->trigger.value_type = pProtocolWaitConds->value_type; + XSyncIntsToValue(&pAwait->trigger.wait_value, + pProtocolWaitConds->wait_value_lo, + pProtocolWaitConds->wait_value_hi); + pAwait->trigger.test_type = pProtocolWaitConds->test_type; + + status = SyncInitTrigger(client, &pAwait->trigger, + pProtocolWaitConds->counter, + XSyncCAAllTrigger); + if (status != Success) { + /* this should take care of removing any triggers created by + * this request that have already been registered on counters + */ + FreeResource(pAwaitUnion->header.delete_id, RT_NONE); + return status; + } + /* this is not a mistake -- same function works for both cases */ + pAwait->trigger.TriggerFired = SyncAwaitTriggerFired; + pAwait->trigger.CounterDestroyed = SyncAwaitTriggerFired; + XSyncIntsToValue(&pAwait->event_threshold, + pProtocolWaitConds->event_threshold_lo, + pProtocolWaitConds->event_threshold_hi); + pAwait->pHeader = &pAwaitUnion->header; + pAwaitUnion->header.num_waitconditions++; + } + + IgnoreClient(client); + + /* see if any of the triggers are already true */ + + pAwait = &(pAwaitUnion + 1)->await; /* skip over header */ + for (i = 0; i < items; i++, pAwait++) { + /* don't have to worry about NULL counters because the request + * errors before we get here out if they occur + */ + if ((*pAwait->trigger.CheckTrigger) (&pAwait->trigger, + pAwait->trigger.pCounter->value)) { + (*pAwait->trigger.TriggerFired) (&pAwait->trigger); + break; /* once is enough */ + } + } + return Success; +} + +/* + * ** Query a counter + */ +static int +ProcSyncQueryCounter(client) +ClientPtr client; +{ + REQUEST(xSyncQueryCounterReq); + xSyncQueryCounterReply rep; + + SyncCounter *pCounter; + + REQUEST_SIZE_MATCH(xSyncQueryCounterReq); + + pCounter = (SyncCounter *) SecurityLookupIDByType(client, stuff->counter, + RTCounter, + SecurityReadAccess); + if (pCounter == NULL) { + client->errorValue = stuff->counter; + return SyncErrorBase + XSyncBadCounter; + } + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + /* if system counter, ask it what the current value is */ + + if (IsSystemCounter(pCounter)) { + (*pCounter->pSysCounterInfo->QueryValue) ((pointer) pCounter, + &pCounter->value); + } + + rep.value_hi = XSyncValueHigh32(pCounter->value); + rep.value_lo = XSyncValueLow32(pCounter->value); + if (client->swapped) { + + swaps(&rep.sequenceNumber); + swapl(&rep.length); + swapl(&rep.value_hi); + swapl(&rep.value_lo); + } + WriteToClient(client, sizeof(xSyncQueryCounterReply), (char *) &rep); + return (client->noClientException); +} + +/* + * ** Create Alarm + */ +static int +ProcSyncCreateAlarm(client) +ClientPtr client; +{ + REQUEST(xSyncCreateAlarmReq); + SyncAlarm *pAlarm; + + int status; + + unsigned long len, vmask; + + SyncTrigger *pTrigger; + + REQUEST_AT_LEAST_SIZE(xSyncCreateAlarmReq); + + LEGAL_NEW_RESOURCE(stuff->id, client); + + vmask = stuff->valueMask; + len = client->req_len - (sizeof(xSyncCreateAlarmReq) >> 2); + /* the "extra" call to Ones accounts for the presence of 64 bit values */ + if (len != (Ones(vmask) + Ones(vmask & (XSyncCAValue | XSyncCADelta)))) + return BadLength; + + if (!(pAlarm = malloc(sizeof(SyncAlarm)))) { + return BadAlloc; + } + + /* set up defaults */ + + pTrigger = &pAlarm->trigger; + pTrigger->pCounter = NULL; + pTrigger->value_type = XSyncAbsolute; + XSyncIntToValue(&pTrigger->wait_value, 0L); + pTrigger->test_type = XSyncPositiveComparison; + pTrigger->TriggerFired = SyncAlarmTriggerFired; + pTrigger->CounterDestroyed = SyncAlarmCounterDestroyed; + status = SyncInitTrigger(client, pTrigger, None, XSyncCAAllTrigger); + if (status != Success) { + free(pAlarm); + return status; + } + + pAlarm->client = client; + pAlarm->alarm_id = stuff->id; + XSyncIntToValue(&pAlarm->delta, 1L); + pAlarm->events = TRUE; + pAlarm->state = XSyncAlarmInactive; + pAlarm->pEventClients = NULL; + status = SyncChangeAlarmAttributes(client, pAlarm, vmask, + (CARD32 *) &stuff[1]); + if (status != Success) { + free(pAlarm); + return status; + } + + if (!AddResource(stuff->id, RTAlarm, pAlarm)) { + free(pAlarm); + return BadAlloc; + } + + /* see if alarm already triggered. NULL counter will not trigger + * in CreateAlarm and sets alarm state to Inactive. + */ + + if (!pTrigger->pCounter) { + pAlarm->state = XSyncAlarmInactive; /* XXX protocol change */ + } + else if ((*pTrigger->CheckTrigger) (pTrigger, pTrigger->pCounter->value)) { + (*pTrigger->TriggerFired) (pTrigger); + } + + return Success; +} + +/* + * ** Change Alarm + */ +static int +ProcSyncChangeAlarm(client) +ClientPtr client; +{ + REQUEST(xSyncChangeAlarmReq); + SyncAlarm *pAlarm; + + long vmask; + + int len, status; + + REQUEST_AT_LEAST_SIZE(xSyncChangeAlarmReq); + + if (!(pAlarm = (SyncAlarm *) SecurityLookupIDByType(client, stuff->alarm, + RTAlarm, + SecurityWriteAccess))) { + client->errorValue = stuff->alarm; + return SyncErrorBase + XSyncBadAlarm; + } + + vmask = stuff->valueMask; + len = client->req_len - (sizeof(xSyncChangeAlarmReq) >> 2); + /* the "extra" call to Ones accounts for the presence of 64 bit values */ + if (len != (Ones(vmask) + Ones(vmask & (XSyncCAValue | XSyncCADelta)))) + return BadLength; + + if ((status = SyncChangeAlarmAttributes(client, pAlarm, vmask, + (CARD32 *) &stuff[1])) != Success) + return status; + + /* see if alarm already triggered. NULL counter WILL trigger + * in ChangeAlarm. + */ + + if (!pAlarm->trigger.pCounter || + (*pAlarm->trigger.CheckTrigger) (&pAlarm->trigger, + pAlarm->trigger.pCounter->value)) { + (*pAlarm->trigger.TriggerFired) (&pAlarm->trigger); + } + return Success; +} + +static int +ProcSyncQueryAlarm(client) +ClientPtr client; +{ + REQUEST(xSyncQueryAlarmReq); + SyncAlarm *pAlarm; + + xSyncQueryAlarmReply rep; + + SyncTrigger *pTrigger; + + REQUEST_SIZE_MATCH(xSyncQueryAlarmReq); + + pAlarm = (SyncAlarm *) SecurityLookupIDByType(client, stuff->alarm, + RTAlarm, SecurityReadAccess); + if (!pAlarm) { + client->errorValue = stuff->alarm; + return (SyncErrorBase + XSyncBadAlarm); + } + + rep.type = X_Reply; + rep.length = (sizeof(xSyncQueryAlarmReply) - sizeof(xGenericReply)) >> 2; + rep.sequenceNumber = client->sequence; + + pTrigger = &pAlarm->trigger; + rep.counter = (pTrigger->pCounter) ? pTrigger->pCounter->id : None; + +#if 0 /* XXX unclear what to do, depends on whether relative value-types + * are "consumed" immediately and are considered absolute from then + * on. + */ + rep.value_type = pTrigger->value_type; + rep.wait_value_hi = XSyncValueHigh32(pTrigger->wait_value); + rep.wait_value_lo = XSyncValueLow32(pTrigger->wait_value); +#else + rep.value_type = XSyncAbsolute; + rep.wait_value_hi = XSyncValueHigh32(pTrigger->test_value); + rep.wait_value_lo = XSyncValueLow32(pTrigger->test_value); +#endif + + rep.test_type = pTrigger->test_type; + rep.delta_hi = XSyncValueHigh32(pAlarm->delta); + rep.delta_lo = XSyncValueLow32(pAlarm->delta); + rep.events = pAlarm->events; + rep.state = pAlarm->state; + + if (client->swapped) { + + swaps(&rep.sequenceNumber); + swapl(&rep.length); + swapl(&rep.counter); + swapl(&rep.wait_value_hi); + swapl(&rep.wait_value_lo); + swapl(&rep.test_type); + swapl(&rep.delta_hi); + swapl(&rep.delta_lo); + } + + WriteToClient(client, sizeof(xSyncQueryAlarmReply), (char *) &rep); + return (client->noClientException); +} + +static int +ProcSyncDestroyAlarm(client) +ClientPtr client; +{ + REQUEST(xSyncDestroyAlarmReq); + + REQUEST_SIZE_MATCH(xSyncDestroyAlarmReq); + + if (!((SyncAlarm *) SecurityLookupIDByType(client, stuff->alarm, + RTAlarm, SecurityDestroyAccess))) + { + client->errorValue = stuff->alarm; + return SyncErrorBase + XSyncBadAlarm; + } + + FreeResource(stuff->alarm, RT_NONE); + return (client->noClientException); +} + +/* + * ** Given an extension request, call the appropriate request procedure + */ +static int +ProcSyncDispatch(client) +ClientPtr client; +{ + REQUEST(xReq); + + switch (stuff->data) { + + case X_SyncInitialize: + return ProcSyncInitialize(client); + case X_SyncListSystemCounters: + return ProcSyncListSystemCounters(client); + case X_SyncCreateCounter: + return ProcSyncCreateCounter(client); + case X_SyncSetCounter: + return ProcSyncSetCounter(client); + case X_SyncChangeCounter: + return ProcSyncChangeCounter(client); + case X_SyncQueryCounter: + return ProcSyncQueryCounter(client); + case X_SyncDestroyCounter: + return ProcSyncDestroyCounter(client); + case X_SyncAwait: + return ProcSyncAwait(client); + case X_SyncCreateAlarm: + return ProcSyncCreateAlarm(client); + case X_SyncChangeAlarm: + return ProcSyncChangeAlarm(client); + case X_SyncQueryAlarm: + return ProcSyncQueryAlarm(client); + case X_SyncDestroyAlarm: + return ProcSyncDestroyAlarm(client); + case X_SyncSetPriority: + return ProcSyncSetPriority(client); + case X_SyncGetPriority: + return ProcSyncGetPriority(client); + default: + return BadRequest; + } +} + +/* + * Boring Swapping stuff ... + */ + +static int +SProcSyncInitialize(client) +ClientPtr client; +{ + REQUEST(xSyncInitializeReq); + + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xSyncInitializeReq); + + return ProcSyncInitialize(client); +} + +static int +SProcSyncListSystemCounters(client) +ClientPtr client; +{ + REQUEST(xSyncListSystemCountersReq); + + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xSyncListSystemCountersReq); + + return ProcSyncListSystemCounters(client); +} + +static int +SProcSyncCreateCounter(client) +ClientPtr client; +{ + REQUEST(xSyncCreateCounterReq); + + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xSyncCreateCounterReq); + swapl(&stuff->cid); + swapl(&stuff->initial_value_lo); + swapl(&stuff->initial_value_hi); + + return ProcSyncCreateCounter(client); +} + +static int +SProcSyncSetCounter(client) +ClientPtr client; +{ + REQUEST(xSyncSetCounterReq); + + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xSyncSetCounterReq); + swapl(&stuff->cid); + swapl(&stuff->value_lo); + swapl(&stuff->value_hi); + + return ProcSyncSetCounter(client); +} + +static int +SProcSyncChangeCounter(client) +ClientPtr client; +{ + REQUEST(xSyncChangeCounterReq); + + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xSyncChangeCounterReq); + swapl(&stuff->cid); + swapl(&stuff->value_lo); + swapl(&stuff->value_hi); + + return ProcSyncChangeCounter(client); +} + +static int +SProcSyncQueryCounter(client) +ClientPtr client; +{ + REQUEST(xSyncQueryCounterReq); + + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xSyncQueryCounterReq); + swapl(&stuff->counter); + + return ProcSyncQueryCounter(client); +} + +static int +SProcSyncDestroyCounter(client) +ClientPtr client; +{ + REQUEST(xSyncDestroyCounterReq); + + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xSyncDestroyCounterReq); + swapl(&stuff->counter); + + return ProcSyncDestroyCounter(client); +} + +static int +SProcSyncAwait(client) +ClientPtr client; +{ + REQUEST(xSyncAwaitReq); + + swaps(&stuff->length); + REQUEST_AT_LEAST_SIZE(xSyncAwaitReq); + SwapRestL(stuff); + + return ProcSyncAwait(client); +} + +static int +SProcSyncCreateAlarm(client) +ClientPtr client; +{ + REQUEST(xSyncCreateAlarmReq); + + swaps(&stuff->length); + REQUEST_AT_LEAST_SIZE(xSyncCreateAlarmReq); + swapl(&stuff->id); + swapl(&stuff->valueMask); + SwapRestL(stuff); + + return ProcSyncCreateAlarm(client); +} + +static int +SProcSyncChangeAlarm(client) +ClientPtr client; +{ + REQUEST(xSyncChangeAlarmReq); + + swaps(&stuff->length); + REQUEST_AT_LEAST_SIZE(xSyncChangeAlarmReq); + swapl(&stuff->alarm); + swapl(&stuff->valueMask); + SwapRestL(stuff); + return ProcSyncChangeAlarm(client); +} + +static int +SProcSyncQueryAlarm(client) +ClientPtr client; +{ + REQUEST(xSyncQueryAlarmReq); + + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xSyncQueryAlarmReq); + swapl(&stuff->alarm); + + return ProcSyncQueryAlarm(client); +} + +static int +SProcSyncDestroyAlarm(client) +ClientPtr client; +{ + REQUEST(xSyncDestroyAlarmReq); + + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xSyncDestroyAlarmReq); + swapl(&stuff->alarm); + + return ProcSyncDestroyAlarm(client); +} + +static int +SProcSyncSetPriority(client) +ClientPtr client; +{ + REQUEST(xSyncSetPriorityReq); + + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xSyncSetPriorityReq); + swapl(&stuff->id); + swapl(&stuff->priority); + + return ProcSyncSetPriority(client); +} + +static int +SProcSyncGetPriority(client) +ClientPtr client; +{ + REQUEST(xSyncGetPriorityReq); + + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xSyncGetPriorityReq); + swapl(&stuff->id); + + return ProcSyncGetPriority(client); +} + +static int +SProcSyncDispatch(client) +ClientPtr client; +{ + REQUEST(xReq); + + switch (stuff->data) { + case X_SyncInitialize: + return SProcSyncInitialize(client); + case X_SyncListSystemCounters: + return SProcSyncListSystemCounters(client); + case X_SyncCreateCounter: + return SProcSyncCreateCounter(client); + case X_SyncSetCounter: + return SProcSyncSetCounter(client); + case X_SyncChangeCounter: + return SProcSyncChangeCounter(client); + case X_SyncQueryCounter: + return SProcSyncQueryCounter(client); + case X_SyncDestroyCounter: + return SProcSyncDestroyCounter(client); + case X_SyncAwait: + return SProcSyncAwait(client); + case X_SyncCreateAlarm: + return SProcSyncCreateAlarm(client); + case X_SyncChangeAlarm: + return SProcSyncChangeAlarm(client); + case X_SyncQueryAlarm: + return SProcSyncQueryAlarm(client); + case X_SyncDestroyAlarm: + return SProcSyncDestroyAlarm(client); + case X_SyncSetPriority: + return SProcSyncSetPriority(client); + case X_SyncGetPriority: + return SProcSyncGetPriority(client); + default: + return BadRequest; + } +} + +/* + * Event Swapping + */ + +static void +SCounterNotifyEvent(from, to) +xSyncCounterNotifyEvent *from, *to; +{ + to->type = from->type; + to->kind = from->kind; + cpswaps(from->sequenceNumber, to->sequenceNumber); + cpswapl(from->counter, to->counter); + cpswapl(from->wait_value_lo, to->wait_value_lo); + cpswapl(from->wait_value_hi, to->wait_value_hi); + cpswapl(from->counter_value_lo, to->counter_value_lo); + cpswapl(from->counter_value_hi, to->counter_value_hi); + cpswapl(from->time, to->time); + cpswaps(from->count, to->count); + to->destroyed = from->destroyed; +} + +static void +SAlarmNotifyEvent(from, to) +xSyncAlarmNotifyEvent *from, *to; +{ + to->type = from->type; + to->kind = from->kind; + cpswaps(from->sequenceNumber, to->sequenceNumber); + cpswapl(from->alarm, to->alarm); + cpswapl(from->counter_value_lo, to->counter_value_lo); + cpswapl(from->counter_value_hi, to->counter_value_hi); + cpswapl(from->alarm_value_lo, to->alarm_value_lo); + cpswapl(from->alarm_value_hi, to->alarm_value_hi); + cpswapl(from->time, to->time); + to->state = from->state; +} + +/* + * ** Close everything down. ** This is fairly simple for now. + */ +/* ARGSUSED */ +static void +SyncResetProc(extEntry) +ExtensionEntry *extEntry; +{ + free(SysCounterList); + SysCounterList = NULL; + RTCounter = 0; +} + +/* + * ** Initialise the extension. + */ +void +SyncExtensionInit(INITARGS) +{ + ExtensionEntry *extEntry; + + if (RTCounter == 0) { + RTCounter = CreateNewResourceType(FreeCounter); + } + RTAlarm = CreateNewResourceType(FreeAlarm); + RTAwait = CreateNewResourceType(FreeAwait) | RC_NEVERRETAIN; + RTAlarmClient = CreateNewResourceType(FreeAlarmClient) | RC_NEVERRETAIN; + + if (RTCounter == 0 || RTAwait == 0 || RTAlarm == 0 || + RTAlarmClient == 0 || + (extEntry = AddExtension(SYNC_NAME, + XSyncNumberEvents, XSyncNumberErrors, + ProcSyncDispatch, SProcSyncDispatch, + SyncResetProc, StandardMinorOpcode)) == NULL) { + ErrorF("Sync Extension %d.%d failed to Initialise\n", + SYNC_MAJOR_VERSION, SYNC_MINOR_VERSION); + return; + } + + SyncEventBase = extEntry->eventBase; + SyncErrorBase = extEntry->errorBase; + EventSwapVector[SyncEventBase + XSyncCounterNotify] = + (EventSwapPtr) SCounterNotifyEvent; + EventSwapVector[SyncEventBase + XSyncAlarmNotify] = + (EventSwapPtr) SAlarmNotifyEvent; + + /* + * Although SERVERTIME is implemented by the OS layer, we initialise it + * here because doing it in OsInit() is too early. The resource database + * is not initialised when OsInit() is called. This is just about OK + * because there is always a servertime counter. + */ + SyncInitServerTime(); + +#ifdef DEBUG + fprintf(stderr, "Sync Extension %d.%d\n", + SYNC_MAJOR_VERSION, SYNC_MINOR_VERSION); +#endif +} + +/* + * ***** SERVERTIME implementation - should go in its own file in OS directory? + */ + +static pointer ServertimeCounter; + +static XSyncValue Now; + +static XSyncValue *pnext_time; + +#define GetTime()\ +{\ + unsigned long millis = GetTimeInMillis();\ + unsigned long maxis = XSyncValueHigh32(Now);\ + if (millis < XSyncValueLow32(Now)) maxis++;\ + XSyncIntsToValue(&Now, millis, maxis);\ +} + +/* +*** Server Block Handler +*** code inspired by multibuffer extension + */ + /*ARGSUSED*/ static void +ServertimeBlockHandler(env, wt, LastSelectMask) +pointer env; + +struct timeval **wt; + +pointer LastSelectMask; +{ + XSyncValue delay; + + unsigned long timeout; + + if (pnext_time) { + GetTime(); + + if (XSyncValueGreaterOrEqual(Now, *pnext_time)) { + timeout = 0; + } + else { + Bool overflow; + + XSyncValueSubtract(&delay, *pnext_time, Now, &overflow); + (void) overflow; + timeout = XSyncValueLow32(delay); + } + AdjustWaitForDelay(wt, timeout); /* os/utils.c */ + } +} + +/* +*** Wakeup Handler + */ + /*ARGSUSED*/ static void +ServertimeWakeupHandler(env, rc, LastSelectMask) +pointer env; + +int rc; + +pointer LastSelectMask; +{ + if (pnext_time) { + GetTime(); + + if (XSyncValueGreaterOrEqual(Now, *pnext_time)) { + SyncChangeCounter(ServertimeCounter, Now); + } + } +} + +static void +ServertimeQueryValue(pCounter, pValue_return) +pointer pCounter; + +CARD64 *pValue_return; +{ + GetTime(); + *pValue_return = Now; +} + +static void +ServertimeBracketValues(pCounter, pbracket_less, pbracket_greater) +pointer pCounter; + +CARD64 *pbracket_less; + +CARD64 *pbracket_greater; +{ + if (!pnext_time && pbracket_greater) { + RegisterBlockAndWakeupHandlers(ServertimeBlockHandler, + ServertimeWakeupHandler, NULL); + } + else if (pnext_time && !pbracket_greater) { + RemoveBlockAndWakeupHandlers(ServertimeBlockHandler, + ServertimeWakeupHandler, NULL); + } + pnext_time = pbracket_greater; +} + +static void +SyncInitServerTime() +{ + CARD64 resolution; + + XSyncIntsToValue(&Now, GetTimeInMillis(), 0); + XSyncIntToValue(&resolution, 4); + ServertimeCounter = SyncCreateSystemCounter("SERVERTIME", Now, resolution, + XSyncCounterNeverDecreases, + ServertimeQueryValue, + ServertimeBracketValues); + pnext_time = NULL; +} diff --git a/Xext/xcmisc.c b/Xext/xcmisc.c new file mode 100644 index 0000000..d8bfc81 --- /dev/null +++ b/Xext/xcmisc.c @@ -0,0 +1,244 @@ +/* + +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 +#endif + +#include +#include +#include "misc.h" +#include "os.h" +#include "dixstruct.h" +#include "extnsionst.h" +#include "swaprep.h" +#include +#include "extinit.h" + +#if 0 +static unsigned char XCMiscCode; +#endif + +static void XCMiscResetProc(ExtensionEntry * /* extEntry */ + ); + +static DISPATCH_PROC(ProcXCMiscDispatch); + +static DISPATCH_PROC(ProcXCMiscGetVersion); + +static DISPATCH_PROC(ProcXCMiscGetXIDList); + +static DISPATCH_PROC(ProcXCMiscGetXIDRange); + +static DISPATCH_PROC(SProcXCMiscDispatch); + +static DISPATCH_PROC(SProcXCMiscGetVersion); + +static DISPATCH_PROC(SProcXCMiscGetXIDList); + +static DISPATCH_PROC(SProcXCMiscGetXIDRange); + +void +XCMiscExtensionInit(INITARGS) +{ +#if 0 + ExtensionEntry *extEntry; + + if ((extEntry = AddExtension(XCMiscExtensionName, 0, 0, + ProcXCMiscDispatch, SProcXCMiscDispatch, + XCMiscResetProc, StandardMinorOpcode)) != 0) + XCMiscCode = (unsigned char) extEntry->base; +#else + (void) AddExtension(XCMiscExtensionName, 0, 0, + ProcXCMiscDispatch, SProcXCMiscDispatch, + XCMiscResetProc, StandardMinorOpcode); +#endif + + DeclareExtensionSecurity(XCMiscExtensionName, TRUE); +} + + /*ARGSUSED*/ static void +XCMiscResetProc(extEntry) +ExtensionEntry *extEntry; +{ +} + +static int +ProcXCMiscGetVersion(client) +ClientPtr client; +{ + xXCMiscGetVersionReply rep; + + + REQUEST_SIZE_MATCH(xXCMiscGetVersionReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.majorVersion = XCMiscMajorVersion; + rep.minorVersion = XCMiscMinorVersion; + if (client->swapped) { + swaps(&rep.sequenceNumber); + swaps(&rep.majorVersion); + swaps(&rep.minorVersion); + } + WriteToClient(client, sizeof(xXCMiscGetVersionReply), (char *) &rep); + return (client->noClientException); +} + +static int +ProcXCMiscGetXIDRange(client) +ClientPtr client; +{ + xXCMiscGetXIDRangeReply rep; + + + XID min_id, max_id; + + REQUEST_SIZE_MATCH(xXCMiscGetXIDRangeReq); + GetXIDRange(client->index, FALSE, &min_id, &max_id); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.start_id = min_id; + rep.count = max_id - min_id + 1; + if (client->swapped) { + swaps(&rep.sequenceNumber); + swapl(&rep.start_id); + swapl(&rep.count); + } + WriteToClient(client, sizeof(xXCMiscGetXIDRangeReply), (char *) &rep); + return (client->noClientException); +} + +static int +ProcXCMiscGetXIDList(client) +ClientPtr client; +{ + REQUEST(xXCMiscGetXIDListReq); + xXCMiscGetXIDListReply rep; + + + XID *pids; + + unsigned int count; + + REQUEST_SIZE_MATCH(xXCMiscGetXIDListReq); + + pids = (XID *) ALLOCATE_LOCAL(stuff->count * sizeof(XID)); + if (!pids) { + return BadAlloc; + } + count = GetXIDList(client, stuff->count, pids); + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = count; + rep.count = count; + if (client->swapped) { + swaps(&rep.sequenceNumber); + swapl(&rep.length); + swapl(&rep.count); + } + WriteToClient(client, sizeof(xXCMiscGetXIDListReply), (char *) &rep); + if (count) { + client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write; + WriteSwappedDataToClient(client, count * sizeof(XID), pids); + } + DEALLOCATE_LOCAL(pids); + return (client->noClientException); +} + +static int +ProcXCMiscDispatch(client) +ClientPtr client; +{ + REQUEST(xReq); + switch (stuff->data) { + case X_XCMiscGetVersion: + return ProcXCMiscGetVersion(client); + case X_XCMiscGetXIDRange: + return ProcXCMiscGetXIDRange(client); + case X_XCMiscGetXIDList: + return ProcXCMiscGetXIDList(client); + default: + return BadRequest; + } +} + +static int +SProcXCMiscGetVersion(client) +ClientPtr client; +{ + + REQUEST(xXCMiscGetVersionReq); + + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xXCMiscGetVersionReq); + swaps(&stuff->majorVersion); + swaps(&stuff->minorVersion); + return ProcXCMiscGetVersion(client); +} + +static int +SProcXCMiscGetXIDRange(client) +ClientPtr client; +{ + + REQUEST(xReq); + + swaps(&stuff->length); + return ProcXCMiscGetXIDRange(client); +} + +static int +SProcXCMiscGetXIDList(client) +ClientPtr client; +{ + + REQUEST(xXCMiscGetXIDListReq); + + swaps(&stuff->length); + swapl(&stuff->count); + return ProcXCMiscGetXIDList(client); +} + +static int +SProcXCMiscDispatch(client) +ClientPtr client; +{ + REQUEST(xReq); + switch (stuff->data) { + case X_XCMiscGetVersion: + return SProcXCMiscGetVersion(client); + case X_XCMiscGetXIDRange: + return SProcXCMiscGetXIDRange(client); + case X_XCMiscGetXIDList: + return SProcXCMiscGetXIDList(client); + default: + return BadRequest; + } +} diff --git a/Xext/xf86bigfont.c b/Xext/xf86bigfont.c new file mode 100644 index 0000000..c3a04f3 --- /dev/null +++ b/Xext/xf86bigfont.c @@ -0,0 +1,779 @@ +/* + * BIGFONT extension for sharing font metrics between clients (if possible) + * and for transmitting font metrics to clients in a compressed form. + * + * Copyright (c) 1999-2000 Bruno Haible + * Copyright (c) 1999-2000 The XFree86 Project, Inc. + */ + +/* THIS IS NOT AN X CONSORTIUM STANDARD */ + +/* + * Big fonts suffer from the following: All clients that have opened a + * font can access the complete glyph metrics array (the XFontStruct member + * `per_char') directly, without going through a macro. Moreover these + * glyph metrics are ink metrics, i.e. are not redundant even for a + * fixed-width font. For a Unicode font, the size of this array is 768 KB. + * + * Problems: 1. It eats a lot of memory in each client. 2. All this glyph + * metrics data is piped through the socket when the font is opened. + * + * This extension addresses these two problems for local clients, by using + * shared memory. It also addresses the second problem for non-local clients, + * by compressing the data before transmit by a factor of nearly 6. + * + * If you use this extension, your OS ought to nicely support shared memory. + * This means: Shared memory should be swappable to the swap, and the limits + * should be high enough (SHMMNI at least 64, SHMMAX at least 768 KB, + * SHMALL at least 48 MB). It is a plus if your OS allows shmat() calls + * on segments that have already been marked "removed", because it permits + * these segments to be cleaned up by the OS if the X server is killed with + * signal SIGKILL. + * + * This extension is transparently exploited by Xlib (functions XQueryFont, + * XLoadQueryFont). + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#if defined(linux) && (!defined(__GNU_LIBRARY__) || __GNU_LIBRARY__ < 2) +/* libc4 does not define __GNU_LIBRARY__, libc5 defines __GNU_LIBRARY__ as 1 */ +/* Linux libc4 and libc5 only (because glibc doesn't include kernel headers): + Linux 2.0.x and 2.2.x define SHMLBA as PAGE_SIZE, but forget to define + PAGE_SIZE. It is defined in . */ +#include +#endif +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "misc.h" +#include "os.h" +#include "dixstruct.h" +#include "gcstruct.h" +#include "dixfontstr.h" +#include "extnsionst.h" + +#define _XF86BIGFONT_SERVER_ +#include + +static void XF86BigfontResetProc(ExtensionEntry * /* extEntry */ + ); + +static DISPATCH_PROC(ProcXF86BigfontDispatch); + +static DISPATCH_PROC(ProcXF86BigfontQueryVersion); + +static DISPATCH_PROC(ProcXF86BigfontQueryFont); + +static DISPATCH_PROC(SProcXF86BigfontDispatch); + +static DISPATCH_PROC(SProcXF86BigfontQueryVersion); + +static DISPATCH_PROC(SProcXF86BigfontQueryFont); + +#if 0 +static unsigned char XF86BigfontReqCode; +#endif + + +/* A random signature, transmitted to the clients so they can verify that the + shared memory segment they are attaching to was really established by the + X server they are talking to. */ +static CARD32 signature; + +/* Index for additional information stored in a FontRec's devPrivates array. */ +static int FontShmdescIndex; + +static unsigned int pagesize; + +static Bool badSysCall = FALSE; + +#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__CYGWIN__) + +#include + +static void +SigSysHandler(int signo) +{ + badSysCall = TRUE; +} + +static Bool +CheckForShmSyscall(void) +{ + void (*oldHandler) (int); + + int shmid = -1; + + /* If no SHM support in the kernel, the bad syscall will generate SIGSYS */ + oldHandler = signal(SIGSYS, SigSysHandler); + + badSysCall = FALSE; + shmid = shmget(IPC_PRIVATE, 4096, IPC_CREAT); + if (shmid != -1) { + /* Successful allocation - clean up */ + shmctl(shmid, IPC_RMID, (struct shmid_ds *) NULL); + } + else { + /* Allocation failed */ + badSysCall = TRUE; + } + signal(SIGSYS, oldHandler); + return (!badSysCall); +} + +#define MUST_CHECK_FOR_SHM_SYSCALL + +#endif + + +void +XFree86BigfontExtensionInit() +{ +#if 0 + ExtensionEntry *extEntry; + + if ((extEntry = AddExtension(XF86BIGFONTNAME, + XF86BigfontNumberEvents, + XF86BigfontNumberErrors, + ProcXF86BigfontDispatch, + SProcXF86BigfontDispatch, + XF86BigfontResetProc, StandardMinorOpcode))) { + XF86BigfontReqCode = (unsigned char) extEntry->base; +#else + if (AddExtension(XF86BIGFONTNAME, + XF86BigfontNumberEvents, + XF86BigfontNumberErrors, + ProcXF86BigfontDispatch, + SProcXF86BigfontDispatch, + XF86BigfontResetProc, StandardMinorOpcode)) { +#endif +#ifdef MUST_CHECK_FOR_SHM_SYSCALL + /* + * Note: Local-clients will not be optimized without shared memory + * support. Remote-client optimization does not depend on shared + * memory support. Thus, the extension is still registered even + * when shared memory support is not functional. + */ + if (!CheckForShmSyscall()) { + ErrorF(XF86BIGFONTNAME + " extension local-client optimization disabled due to lack of shared memory support in the kernel\n"); + return; + } +#endif + + srand((unsigned int) time(NULL)); + signature = ((unsigned int) (65536.0 / (RAND_MAX + 1.0) * rand()) << 16) + + (unsigned int) (65536.0 / (RAND_MAX + 1.0) * rand()); + /* fprintf(stderr, "signature = 0x%08X\n", signature); */ + + FontShmdescIndex = AllocateFontPrivateIndex(); + +#if !defined(CSRG_BASED) && !defined(__CYGWIN__) + pagesize = SHMLBA; +#else +# ifdef _SC_PAGESIZE + pagesize = sysconf(_SC_PAGESIZE); +# else + pagesize = getpagesize(); +# endif +#endif + } +} + +/* ========== Management of shared memory segments ========== */ + + +#ifdef __linux__ +/* On Linux, shared memory marked as "removed" can still be attached. + Nice feature, because the kernel will automatically free the associated + storage when the server and all clients are gone. */ +#define EARLY_REMOVE +#endif + +typedef struct _ShmDesc { + struct _ShmDesc *next; + struct _ShmDesc **prev; + int shmid; + char *attach_addr; +} ShmDescRec, *ShmDescPtr; + +static ShmDescPtr ShmList = (ShmDescPtr) NULL; + +static ShmDescPtr +shmalloc(unsigned int size) +{ + ShmDescPtr pDesc; + + int shmid; + + char *addr; + +#ifdef MUST_CHECK_FOR_SHM_SYSCALL + if (pagesize == 0) + return (ShmDescPtr) NULL; +#endif + + /* On some older Linux systems, the number of shared memory segments + system-wide is 127. In Linux 2.4, it is 4095. + Therefore there is a tradeoff to be made between allocating a + shared memory segment on one hand, and allocating memory and piping + the glyph metrics on the other hand. If the glyph metrics size is + small, we prefer the traditional way. */ + if (size < 3500) + return (ShmDescPtr) NULL; + + pDesc = malloc(sizeof(ShmDescRec)); + if (!pDesc) + return (ShmDescPtr) NULL; + + size = (size + pagesize - 1) & -pagesize; + shmid = shmget(IPC_PRIVATE, size, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH); + if (shmid == -1) { + ErrorF(XF86BIGFONTNAME + " extension: shmget() failed, size = %u, errno = %d\n", size, + errno); + free(pDesc); + return (ShmDescPtr) NULL; + } + + if ((addr = shmat(shmid, 0, 0)) == (char *) -1) { + ErrorF(XF86BIGFONTNAME + " extension: shmat() failed, size = %u, errno = %d\n", size, + errno); + shmctl(shmid, IPC_RMID, (void *) 0); + free(pDesc); + return (ShmDescPtr) NULL; + } + +#ifdef EARLY_REMOVE + shmctl(shmid, IPC_RMID, (void *) 0); +#endif + + pDesc->shmid = shmid; + pDesc->attach_addr = addr; + if (ShmList) + ShmList->prev = &pDesc->next; + pDesc->next = ShmList; + pDesc->prev = &ShmList; + ShmList = pDesc; + + return pDesc; +} + +static void +shmdealloc(ShmDescPtr pDesc) +{ +#ifndef EARLY_REMOVE + shmctl(pDesc->shmid, IPC_RMID, (void *) 0); +#endif + shmdt(pDesc->attach_addr); + + if (pDesc->next) + pDesc->next->prev = pDesc->prev; + *pDesc->prev = pDesc->next; + free(pDesc); +} + + +/* Called when a font is closed. */ +void +XF86BigfontFreeFontShm(FontPtr pFont) +{ + ShmDescPtr pDesc; + + /* If during shutdown of the server, XF86BigfontCleanup() has already + * called shmdealloc() for all segments, we don't need to do it here. + */ + if (!ShmList) + return; + + pDesc = (ShmDescPtr) FontGetPrivate(pFont, FontShmdescIndex); + if (pDesc) + shmdealloc(pDesc); +} + +/* Called upon fatal signal. */ +void +XF86BigfontCleanup() +{ + while (ShmList) + shmdealloc(ShmList); +} + +/* Called when a server generation dies. */ +static void +XF86BigfontResetProc(ExtensionEntry * extEntry) +{ + /* This function is normally called from CloseDownExtensions(), called + * from main(). It will be followed by a call to FreeAllResources(), + * which will call XF86BigfontFreeFontShm() for each font. Thus it + * appears that we do not need to do anything in this function. -- + * But I prefer to write robust code, and not keep shared memory lying + * around when it's not needed any more. (Someone might close down the + * extension without calling FreeAllResources()...) + */ + XF86BigfontCleanup(); +} + +/* ========== Handling of extension specific requests ========== */ + +static int +ProcXF86BigfontQueryVersion(ClientPtr client) +{ + xXF86BigfontQueryVersionReply reply = {0}; + + REQUEST_SIZE_MATCH(xXF86BigfontQueryVersionReq); + reply.type = X_Reply; + reply.length = 0; + reply.sequenceNumber = client->sequence; + reply.majorVersion = XF86BIGFONT_MAJOR_VERSION; + reply.minorVersion = XF86BIGFONT_MINOR_VERSION; + reply.uid = geteuid(); + reply.gid = getegid(); + reply.signature = signature; + reply.capabilities = + (LocalClient(client) && !client->swapped ? XF86Bigfont_CAP_LocalShm : 0) + ; /* may add more bits here in future versions */ + if (client->swapped) { + swaps(&reply.sequenceNumber); + swapl(&reply.length); + swaps(&reply.majorVersion); + swaps(&reply.minorVersion); + swapl(&reply.uid); + swapl(&reply.gid); + swapl(&reply.signature); + } + WriteToClient(client, + sizeof(xXF86BigfontQueryVersionReply), (char *) &reply); + return client->noClientException; +} + +static void +swapCharInfo(xCharInfo * pCI) +{ + swaps(&pCI->leftSideBearing); + swaps(&pCI->rightSideBearing); + swaps(&pCI->characterWidth); + swaps(&pCI->ascent); + swaps(&pCI->descent); + swaps(&pCI->attributes); +} + +/* static CARD32 hashCI (xCharInfo *p); */ +#define hashCI(p) \ + (CARD32)(((p->leftSideBearing << 27) + (p->leftSideBearing >> 5) + \ + (p->rightSideBearing << 23) + (p->rightSideBearing >> 9) + \ + (p->characterWidth << 16) + \ + (p->ascent << 11) + (p->descent << 6)) ^ p->attributes) + +static int +ProcXF86BigfontQueryFont(ClientPtr client) +{ + FontPtr pFont; + + REQUEST(xXF86BigfontQueryFontReq); + CARD32 stuff_flags; + + xCharInfo *pmax; + + xCharInfo *pmin; + + int nCharInfos; + + int shmid; + + ShmDescPtr pDesc; + xCharInfo *pCI; + + CARD16 *pIndex2UniqIndex; + + CARD16 *pUniqIndex2Index; + + CARD32 nUniqCharInfos; + +#if 0 + REQUEST_SIZE_MATCH(xXF86BigfontQueryFontReq); +#else + switch (client->req_len) { + case 2: /* client with version 1.0 libX11 */ + stuff_flags = (LocalClient(client) && + !client->swapped ? XF86Bigfont_FLAGS_Shm : 0); + break; + case 3: /* client with version 1.1 libX11 */ + stuff_flags = stuff->flags; + break; + default: + return BadLength; + } +#endif + 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 */ + GC *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; + } + + pmax = FONTINKMAX(pFont); + pmin = FONTINKMIN(pFont); + nCharInfos = + (pmax->rightSideBearing == pmin->rightSideBearing + && pmax->leftSideBearing == pmin->leftSideBearing + && pmax->descent == pmin->descent + && pmax->ascent == pmin->ascent + && pmax->characterWidth == pmin->characterWidth) + ? 0 : N2dChars(pFont); + shmid = -1; + pCI = NULL; + pIndex2UniqIndex = NULL; + pUniqIndex2Index = NULL; + nUniqCharInfos = 0; + + if (nCharInfos > 0) { + if (!badSysCall) + pDesc = (ShmDescPtr) FontGetPrivate(pFont, FontShmdescIndex); + else + pDesc = NULL; + if (pDesc) { + pCI = (xCharInfo *) pDesc->attach_addr; + if (stuff_flags & XF86Bigfont_FLAGS_Shm) + shmid = pDesc->shmid; + } + else { + if (stuff_flags & XF86Bigfont_FLAGS_Shm && !badSysCall) + pDesc = shmalloc(nCharInfos * sizeof(xCharInfo) + + sizeof(CARD32)); + if (pDesc) { + pCI = (xCharInfo *) pDesc->attach_addr; + shmid = pDesc->shmid; + } + else { + pCI = (xCharInfo *) + ALLOCATE_LOCAL(nCharInfos * sizeof(xCharInfo)); + if (!pCI) + return BadAlloc; + } + /* Fill nCharInfos starting at pCI. */ + { + xCharInfo *prCI = pCI; + + int ninfos = 0; + + int ncols = pFont->info.lastCol - pFont->info.firstCol + 1; + + int row; + + for (row = pFont->info.firstRow; + row <= pFont->info.lastRow && ninfos < nCharInfos; row++) { + unsigned char chars[512]; + + xCharInfo *tmpCharInfos[256]; + + unsigned long count; + + int col; + + unsigned long i; + + i = 0; + for (col = pFont->info.firstCol; + col <= pFont->info.lastCol; col++) { + chars[i++] = row; + chars[i++] = col; + } + (*pFont->get_metrics) (pFont, ncols, chars, TwoD16Bit, + &count, tmpCharInfos); + for (i = 0; i < count && ninfos < nCharInfos; i++) { + *prCI++ = *tmpCharInfos[i]; + ninfos++; + } + } + } + if (pDesc && !badSysCall) { + *(CARD32 *) (pCI + nCharInfos) = signature; + if (!FontSetPrivate(pFont, FontShmdescIndex, pDesc)) { + shmdealloc(pDesc); + return BadAlloc; + } + } + } + if (shmid == -1) { + /* Cannot use shared memory, so remove-duplicates the xCharInfos + using a temporary hash table. */ + /* Note that CARD16 is suitable as index type, because + nCharInfos <= 0x10000. */ + CARD32 hashModulus; + + CARD16 *pHash2UniqIndex; + + CARD16 *pUniqIndex2NextUniqIndex; + + CARD32 NextIndex; + + CARD32 NextUniqIndex; + + CARD16 *tmp; + + CARD32 i, j; + + hashModulus = 67; + if (hashModulus > nCharInfos + 1) + hashModulus = nCharInfos + 1; + + tmp = (CARD16 *) + ALLOCATE_LOCAL((4 * nCharInfos + 1) * sizeof(CARD16)); + if (!tmp) { + if (!pDesc) + DEALLOCATE_LOCAL(pCI); + return BadAlloc; + } + pIndex2UniqIndex = tmp; + /* nCharInfos elements */ + pUniqIndex2Index = tmp + nCharInfos; + /* max. nCharInfos elements */ + pUniqIndex2NextUniqIndex = tmp + 2 * nCharInfos; + /* max. nCharInfos elements */ + pHash2UniqIndex = tmp + 3 * nCharInfos; + /* hashModulus (<= nCharInfos+1) elements */ + + /* Note that we can use 0xffff as end-of-list indicator, because + even if nCharInfos = 0x10000, 0xffff can not occur as valid + entry before the last element has been inserted. And once the + last element has been inserted, we don't need the hash table + any more. */ + for (j = 0; j < hashModulus; j++) + pHash2UniqIndex[j] = (CARD16) (-1); + + NextUniqIndex = 0; + for (NextIndex = 0; NextIndex < nCharInfos; NextIndex++) { + xCharInfo *p = &pCI[NextIndex]; + + CARD32 hashCode = hashCI(p) % hashModulus; + + for (i = pHash2UniqIndex[hashCode]; + i != (CARD16) (-1); i = pUniqIndex2NextUniqIndex[i]) { + j = pUniqIndex2Index[i]; + if (pCI[j].leftSideBearing == p->leftSideBearing + && pCI[j].rightSideBearing == p->rightSideBearing + && pCI[j].characterWidth == p->characterWidth + && pCI[j].ascent == p->ascent + && pCI[j].descent == p->descent + && pCI[j].attributes == p->attributes) + break; + } + if (i != (CARD16) (-1)) { + /* Found *p at Index j, UniqIndex i */ + pIndex2UniqIndex[NextIndex] = i; + } + else { + /* Allocate a new entry in the Uniq table */ + if (hashModulus <= 2 * NextUniqIndex + && hashModulus < nCharInfos + 1) { + /* Time to increate hash table size */ + hashModulus = 2 * hashModulus + 1; + if (hashModulus > nCharInfos + 1) + hashModulus = nCharInfos + 1; + for (j = 0; j < hashModulus; j++) + pHash2UniqIndex[j] = (CARD16) (-1); + for (i = 0; i < NextUniqIndex; i++) + pUniqIndex2NextUniqIndex[i] = (CARD16) (-1); + for (i = 0; i < NextUniqIndex; i++) { + j = pUniqIndex2Index[i]; + p = &pCI[j]; + hashCode = hashCI(p) % hashModulus; + pUniqIndex2NextUniqIndex[i] = + pHash2UniqIndex[hashCode]; + pHash2UniqIndex[hashCode] = i; + } + p = &pCI[NextIndex]; + hashCode = hashCI(p) % hashModulus; + } + i = NextUniqIndex++; + pUniqIndex2NextUniqIndex[i] = pHash2UniqIndex[hashCode]; + pHash2UniqIndex[hashCode] = i; + pUniqIndex2Index[i] = NextIndex; + pIndex2UniqIndex[NextIndex] = i; + } + } + nUniqCharInfos = NextUniqIndex; + /* fprintf(stderr, "font metrics: nCharInfos = %d, nUniqCharInfos = %d, hashModulus = %d\n", nCharInfos, nUniqCharInfos, hashModulus); */ + } + } + + { + int nfontprops = pFont->info.nprops; + + int rlength = sizeof(xXF86BigfontQueryFontReply) + + nfontprops * sizeof(xFontProp) + + (nCharInfos > 0 && shmid == -1 + ? nUniqCharInfos * sizeof(xCharInfo) + + (nCharInfos + 1) / 2 * 2 * sizeof(CARD16) + : 0); + + xXF86BigfontQueryFontReply *reply = + (xXF86BigfontQueryFontReply *) ALLOCATE_LOCAL(rlength); + char *p; + + if (!reply) { + if (nCharInfos > 0) { + if (shmid == -1) + DEALLOCATE_LOCAL(pIndex2UniqIndex); + if (!pDesc) + DEALLOCATE_LOCAL(pCI); + } + return BadAlloc; + } + memset(reply, 0, rlength); + + reply->type = X_Reply; + reply->length = (rlength - sizeof(xGenericReply)) >> 2; + reply->sequenceNumber = client->sequence; + reply->minBounds = pFont->info.ink_minbounds; + reply->maxBounds = pFont->info.ink_maxbounds; + reply->minCharOrByte2 = pFont->info.firstCol; + reply->maxCharOrByte2 = pFont->info.lastCol; + reply->defaultChar = pFont->info.defaultCh; + reply->nFontProps = pFont->info.nprops; + reply->drawDirection = pFont->info.drawDirection; + reply->minByte1 = pFont->info.firstRow; + reply->maxByte1 = pFont->info.lastRow; + reply->allCharsExist = pFont->info.allExist; + reply->fontAscent = pFont->info.fontAscent; + reply->fontDescent = pFont->info.fontDescent; + reply->nCharInfos = nCharInfos; + reply->nUniqCharInfos = nUniqCharInfos; + reply->shmid = shmid; + reply->shmsegoffset = 0; + if (client->swapped) { + swaps(&reply->sequenceNumber); + swapl(&reply->length); + swapCharInfo(&reply->minBounds); + swapCharInfo(&reply->maxBounds); + swaps(&reply->minCharOrByte2); + swaps(&reply->maxCharOrByte2); + swaps(&reply->defaultChar); + swaps(&reply->nFontProps); + swaps(&reply->fontAscent); + swaps(&reply->fontDescent); + swapl(&reply->nCharInfos); + swapl(&reply->nUniqCharInfos); + swapl(&reply->shmid); + swapl(&reply->shmsegoffset); + } + p = (char *) &reply[1]; + { + FontPropPtr pFP; + + xFontProp *prFP; + + int i; + + for (i = 0, pFP = pFont->info.props, prFP = (xFontProp *) p; + i < nfontprops; i++, pFP++, prFP++) { + prFP->name = pFP->name; + prFP->value = pFP->value; + if (client->swapped) { + swapl(&prFP->name); + swapl(&prFP->value); + } + } + p = (char *) prFP; + } + if (nCharInfos > 0 && shmid == -1) { + xCharInfo *pci; + + CARD16 *ps; + + int i, j; + + pci = (xCharInfo *) p; + for (i = 0; i < nUniqCharInfos; i++, pci++) { + *pci = pCI[pUniqIndex2Index[i]]; + if (client->swapped) + swapCharInfo(pci); + } + ps = (CARD16 *) pci; + for (j = 0; j < nCharInfos; j++, ps++) { + *ps = pIndex2UniqIndex[j]; + if (client->swapped) { + swaps(ps); + } + } + } + WriteToClient(client, rlength, (char *) reply); + DEALLOCATE_LOCAL(reply); + if (nCharInfos > 0) { + if (shmid == -1) + DEALLOCATE_LOCAL(pIndex2UniqIndex); + if (!pDesc) + DEALLOCATE_LOCAL(pCI); + } + return (client->noClientException); + } +} + +static int +ProcXF86BigfontDispatch(ClientPtr client) +{ + REQUEST(xReq); + + switch (stuff->data) { + case X_XF86BigfontQueryVersion: + return ProcXF86BigfontQueryVersion(client); + case X_XF86BigfontQueryFont: + return ProcXF86BigfontQueryFont(client); + default: + return BadRequest; + } +} + +static int +SProcXF86BigfontQueryVersion(ClientPtr client) +{ + REQUEST(xXF86BigfontQueryVersionReq); + swaps(&stuff->length); + return ProcXF86BigfontQueryVersion(client); +} + +static int +SProcXF86BigfontQueryFont(ClientPtr client) +{ + REQUEST(xXF86BigfontQueryFontReq); + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xXF86BigfontQueryFontReq); + swapl(&stuff->id); + return ProcXF86BigfontQueryFont(client); +} + +static int +SProcXF86BigfontDispatch(ClientPtr client) +{ + REQUEST(xReq); + + switch (stuff->data) { + case X_XF86BigfontQueryVersion: + return SProcXF86BigfontQueryVersion(client); + case X_XF86BigfontQueryFont: + return SProcXF86BigfontQueryFont(client); + default: + return BadRequest; + } +} diff --git a/Xext/xf86bigfontsrv.h b/Xext/xf86bigfontsrv.h new file mode 100644 index 0000000..eab5287 --- /dev/null +++ b/Xext/xf86bigfontsrv.h @@ -0,0 +1,33 @@ +/* + * Copyright © 2010 Yaakov Selkowitz + * + * 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, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) 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 AUTHORS OR COPYRIGHT HOLDERS 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. + */ + +#ifndef _XF86BIGFONTSRV_H_ +#define _XF86BIGFONTSRV_H_ + +#include + +extern void XF86BigfontFreeFontShm(FontPtr); +extern void XF86BigfontCleanup(void); + +#endif diff --git a/Xext/xres.c b/Xext/xres.c new file mode 100644 index 0000000..39ba82e --- /dev/null +++ b/Xext/xres.c @@ -0,0 +1,392 @@ +/* + Copyright (c) 2002 XFree86 Inc +*/ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include "misc.h" +#include "os.h" +#include "dixstruct.h" +#include "extnsionst.h" +#include "swaprep.h" +#include +#include "pixmapstr.h" +#include "windowstr.h" +#include "gcstruct.h" +#include "extinit.h" + +static int +ProcXResQueryVersion(ClientPtr client) +{ + xXResQueryVersionReply rep; + + REQUEST_SIZE_MATCH(xXResQueryVersionReq); + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.server_major = XRES_MAJOR_VERSION; + rep.server_minor = XRES_MINOR_VERSION; + if (client->swapped) { + swaps(&rep.sequenceNumber); + swapl(&rep.length); + swaps(&rep.server_major); + swaps(&rep.server_minor); + } + WriteToClient(client, sizeof(xXResQueryVersionReply), (char *) &rep); + return (client->noClientException); +} + +static int +ProcXResQueryClients(ClientPtr client) +{ + /* REQUEST(xXResQueryClientsReq); */ + xXResQueryClientsReply rep; + + int *current_clients; + + int i, num_clients; + + REQUEST_SIZE_MATCH(xXResQueryClientsReq); + + current_clients = ALLOCATE_LOCAL((currentMaxClients - 1) * sizeof(int)); + + num_clients = 0; + for (i = 1; i < currentMaxClients; i++) { + if (clients[i]) { + current_clients[num_clients] = i; + num_clients++; + } + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.num_clients = num_clients; + rep.length = rep.num_clients * sz_xXResClient >> 2; + if (client->swapped) { + swaps(&rep.sequenceNumber); + swapl(&rep.length); + swapl(&rep.num_clients); + } + WriteToClient(client, sizeof(xXResQueryClientsReply), (char *) &rep); + + if (num_clients) { + xXResClient scratch; + + for (i = 0; i < num_clients; i++) { + scratch.resource_base = clients[current_clients[i]]->clientAsMask; + scratch.resource_mask = RESOURCE_ID_MASK; + + if (client->swapped) { + + swapl(&scratch.resource_base); + swapl(&scratch.resource_mask); + } + WriteToClient(client, sz_xXResClient, (char *) &scratch); + } + } + + DEALLOCATE_LOCAL(current_clients); + + return (client->noClientException); +} + +static void +ResFindAllRes(pointer value, XID id, RESTYPE type, pointer cdata) +{ + int *counts = (int *) cdata; + + counts[(type & TypeMask) - 1]++; +} + +static int +ProcXResQueryClientResources(ClientPtr client) +{ + REQUEST(xXResQueryClientResourcesReq); + xXResQueryClientResourcesReply rep; + + int i, clientID, num_types; + + int *counts; + + REQUEST_SIZE_MATCH(xXResQueryClientResourcesReq); + + clientID = CLIENT_ID(stuff->xid); + + /* we could remove the (clientID == 0) check if we wanted to allow + probing the X-server's resource usage */ + if (!clientID || (clientID >= currentMaxClients) || !clients[clientID]) { + client->errorValue = stuff->xid; + return BadValue; + } + + counts = ALLOCATE_LOCAL((lastResourceType + 1) * sizeof(int)); + + memset(counts, 0, (lastResourceType + 1) * sizeof(int)); + + FindAllClientResources(clients[clientID], ResFindAllRes, counts); + + num_types = 0; + + for (i = 0; i <= lastResourceType; i++) { + if (counts[i]) + num_types++; + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.num_types = num_types; + rep.length = rep.num_types * sz_xXResType >> 2; + if (client->swapped) { + swaps(&rep.sequenceNumber); + swapl(&rep.length); + swapl(&rep.num_types); + } + + WriteToClient(client, sizeof(xXResQueryClientResourcesReply), + (char *) &rep); + + if (num_types) { + xXResType scratch; + + for (i = 0; i < lastResourceType; i++) { + if (!counts[i]) + continue; + + if (!ResourceNames[i + 1]) { + char buf[40]; + + snprintf(buf, sizeof(buf), "Unregistered resource %i", i + 1); + RegisterResourceName(i + 1, buf); + } + + scratch.resource_type = ResourceNames[i + 1]; + scratch.count = counts[i]; + + if (client->swapped) { + + swapl(&scratch.resource_type); + swapl(&scratch.count); + } + WriteToClient(client, sz_xXResType, (char *) &scratch); + } + } + + DEALLOCATE_LOCAL(counts); + + return (client->noClientException); +} + +static unsigned long +ResGetApproxPixmapBytes(PixmapPtr pix) +{ + unsigned long nPixels; + + int bytesPerPixel; + + bytesPerPixel = pix->drawable.bitsPerPixel >> 3; + nPixels = pix->drawable.width * pix->drawable.height; + + /* Divide by refcnt as pixmap could be shared between clients, + * so total pixmap mem is shared between these. + */ + return (nPixels * bytesPerPixel) / pix->refcnt; +} + +static void +ResFindPixmaps(pointer value, XID id, pointer cdata) +{ + unsigned long *bytes = (unsigned long *) cdata; + + PixmapPtr pix = (PixmapPtr) value; + + *bytes += ResGetApproxPixmapBytes(pix); +} + +static void +ResFindWindowPixmaps(pointer value, XID id, pointer cdata) +{ + unsigned long *bytes = (unsigned long *) cdata; + + WindowPtr pWin = (WindowPtr) value; + + if (pWin->backgroundState == BackgroundPixmap) + *bytes += ResGetApproxPixmapBytes(pWin->background.pixmap); + + if (pWin->border.pixmap != NULL && !pWin->borderIsPixel) + *bytes += ResGetApproxPixmapBytes(pWin->border.pixmap); +} + +static void +ResFindGCPixmaps(pointer value, XID id, pointer cdata) +{ + unsigned long *bytes = (unsigned long *) cdata; + + GCPtr pGC = (GCPtr) value; + + if (pGC->stipple != NULL) + *bytes += ResGetApproxPixmapBytes(pGC->stipple); + + if (pGC->tile.pixmap != NULL && !pGC->tileIsPixel) + *bytes += ResGetApproxPixmapBytes(pGC->tile.pixmap); +} + +static int +ProcXResQueryClientPixmapBytes(ClientPtr client) +{ + REQUEST(xXResQueryClientPixmapBytesReq); + xXResQueryClientPixmapBytesReply rep; + + int clientID; + + unsigned long bytes; + + REQUEST_SIZE_MATCH(xXResQueryClientPixmapBytesReq); + + clientID = CLIENT_ID(stuff->xid); + + /* we could remove the (clientID == 0) check if we wanted to allow + probing the X-server's resource usage */ + if (!clientID || (clientID >= currentMaxClients) || !clients[clientID]) { + client->errorValue = stuff->xid; + return BadValue; + } + + bytes = 0; + + FindClientResourcesByType(clients[clientID], RT_PIXMAP, ResFindPixmaps, + (pointer) (&bytes)); + + /* + * Make sure win background pixmaps also held to account. + */ + FindClientResourcesByType(clients[clientID], RT_WINDOW, + ResFindWindowPixmaps, (pointer) (&bytes)); + + /* + * GC Tile & Stipple pixmaps too. + */ + FindClientResourcesByType(clients[clientID], RT_GC, + ResFindGCPixmaps, (pointer) (&bytes)); + + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.bytes = bytes; +#ifdef _XSERVER64 + rep.bytes_overflow = bytes >> 32; +#else + rep.bytes_overflow = 0; +#endif + if (client->swapped) { + swaps(&rep.sequenceNumber); + swapl(&rep.length); + swapl(&rep.bytes); + swapl(&rep.bytes_overflow); + } + WriteToClient(client, sizeof(xXResQueryClientPixmapBytesReply), + (char *) &rep); + + return (client->noClientException); +} + +static void +ResResetProc(ExtensionEntry * extEntry) +{ +} + +static int +ProcResDispatch(ClientPtr client) +{ + REQUEST(xReq); + switch (stuff->data) { + case X_XResQueryVersion: + return ProcXResQueryVersion(client); + case X_XResQueryClients: + return ProcXResQueryClients(client); + case X_XResQueryClientResources: + return ProcXResQueryClientResources(client); + case X_XResQueryClientPixmapBytes: + return ProcXResQueryClientPixmapBytes(client); + default: + break; + } + + return BadRequest; +} + +static int +SProcXResQueryVersion(ClientPtr client) +{ + REQUEST_SIZE_MATCH(xXResQueryVersionReq); + return ProcXResQueryVersion(client); +} + +static int +SProcXResQueryClientResources(ClientPtr client) +{ + REQUEST(xXResQueryClientResourcesReq); + + REQUEST_SIZE_MATCH(xXResQueryClientResourcesReq); + swapl(&stuff->xid); + return ProcXResQueryClientResources(client); +} + +static int +SProcXResQueryClientPixmapBytes(ClientPtr client) +{ + REQUEST(xXResQueryClientPixmapBytesReq); + + REQUEST_SIZE_MATCH(xXResQueryClientPixmapBytesReq); + swapl(&stuff->xid); + return ProcXResQueryClientPixmapBytes(client); +} + +static int +SProcResDispatch(ClientPtr client) +{ + REQUEST(xReq); + + swaps(&stuff->length); + + switch (stuff->data) { + case X_XResQueryVersion: + return SProcXResQueryVersion(client); + case X_XResQueryClients: /* nothing to swap */ + return ProcXResQueryClients(client); + case X_XResQueryClientResources: + return SProcXResQueryClientResources(client); + case X_XResQueryClientPixmapBytes: + return SProcXResQueryClientPixmapBytes(client); + default: + break; + } + + return BadRequest; +} + +void +ResExtensionInit(INITARGS) +{ + (void) AddExtension(XRES_NAME, 0, 0, + ProcResDispatch, SProcResDispatch, + ResResetProc, StandardMinorOpcode); + + RegisterResourceName(RT_NONE, "NONE"); + RegisterResourceName(RT_WINDOW, "WINDOW"); + RegisterResourceName(RT_PIXMAP, "PIXMAP"); + RegisterResourceName(RT_GC, "GC"); + RegisterResourceName(RT_FONT, "FONT"); + RegisterResourceName(RT_CURSOR, "CURSOR"); + RegisterResourceName(RT_COLORMAP, "COLORMAP"); + RegisterResourceName(RT_CMAPENTRY, "COLORMAP ENTRY"); + RegisterResourceName(RT_OTHERCLIENT, "OTHER CLIENT"); + RegisterResourceName(RT_PASSIVEGRAB, "PASSIVE GRAB"); +} diff --git a/Xext/xtest.c b/Xext/xtest.c new file mode 100644 index 0000000..e0f2bdc --- /dev/null +++ b/Xext/xtest.c @@ -0,0 +1,436 @@ +/* + +Copyright 1992, 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 +#endif + +#include +#include +#include "misc.h" +#include "os.h" +#include "dixstruct.h" +#include "extnsionst.h" +#include "windowstr.h" +#include "inputstr.h" +#include "scrnintstr.h" +#include "dixevents.h" +#include "sleepuntil.h" +#define _XTEST_SERVER_ +#include + +#include "extinit.h" + +#if 0 +static unsigned char XTestReqCode; +#endif + + + +static void XTestResetProc(ExtensionEntry * /* extEntry */ + ); + +static int XTestSwapFakeInput(ClientPtr /* client */ , + xReq * /* req */ + ); + +static DISPATCH_PROC(ProcXTestCompareCursor); + +static DISPATCH_PROC(ProcXTestDispatch); + +static DISPATCH_PROC(ProcXTestFakeInput); + +static DISPATCH_PROC(ProcXTestGetVersion); + +static DISPATCH_PROC(ProcXTestGrabControl); + +static DISPATCH_PROC(SProcXTestCompareCursor); + +static DISPATCH_PROC(SProcXTestDispatch); + +static DISPATCH_PROC(SProcXTestFakeInput); + +static DISPATCH_PROC(SProcXTestGetVersion); + +static DISPATCH_PROC(SProcXTestGrabControl); + +void +XTestExtensionInit(INITARGS) +{ +#if 0 + ExtensionEntry *extEntry; + + if ((extEntry = AddExtension(XTestExtensionName, 0, 0, + ProcXTestDispatch, SProcXTestDispatch, + XTestResetProc, StandardMinorOpcode)) != 0) + XTestReqCode = (unsigned char) extEntry->base; +#else + (void) AddExtension(XTestExtensionName, 0, 0, + ProcXTestDispatch, SProcXTestDispatch, + XTestResetProc, StandardMinorOpcode); +#endif +} + + /*ARGSUSED*/ static void +XTestResetProc(extEntry) +ExtensionEntry *extEntry; +{ +} + +static int +ProcXTestGetVersion(client) +ClientPtr client; +{ + xXTestGetVersionReply rep; + + + REQUEST_SIZE_MATCH(xXTestGetVersionReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.majorVersion = XTestMajorVersion; + rep.minorVersion = XTestMinorVersion; + if (client->swapped) { + swaps(&rep.sequenceNumber); + swaps(&rep.minorVersion); + } + WriteToClient(client, sizeof(xXTestGetVersionReply), (char *) &rep); + return (client->noClientException); +} + +static int +ProcXTestCompareCursor(client) +ClientPtr client; +{ + REQUEST(xXTestCompareCursorReq); + xXTestCompareCursorReply rep; + + WindowPtr pWin; + + CursorPtr pCursor; + + + REQUEST_SIZE_MATCH(xXTestCompareCursorReq); + pWin = (WindowPtr) LookupWindow(stuff->window, client); + if (!pWin) + return (BadWindow); + if (stuff->cursor == None) + pCursor = NullCursor; + else if (stuff->cursor == XTestCurrentCursor) + pCursor = GetSpriteCursor(); + else { + pCursor = (CursorPtr) LookupIDByType(stuff->cursor, RT_CURSOR); + if (!pCursor) { + client->errorValue = stuff->cursor; + return (BadCursor); + } + } + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.same = (wCursor(pWin) == pCursor); + if (client->swapped) { + swaps(&rep.sequenceNumber); + } + WriteToClient(client, sizeof(xXTestCompareCursorReply), (char *) &rep); + return (client->noClientException); +} + +static int +ProcXTestFakeInput(client) +ClientPtr client; +{ + REQUEST(xXTestFakeInputReq); + int nev; + + xEvent *ev; + + DeviceIntPtr dev = NULL; + + WindowPtr root; + + int type; + + + nev = (stuff->length << 2) - sizeof(xReq); + if ((nev % sizeof(xEvent)) || !nev) + return BadLength; + nev /= sizeof(xEvent); + UpdateCurrentTime(); + ev = (xEvent *) &((xReq *) stuff)[1]; + type = ev->u.u.type & 0177; + { + if (nev != 1) + return BadLength; + switch (type) { + case KeyPress: + case KeyRelease: + case MotionNotify: + case ButtonPress: + case ButtonRelease: + break; + default: + client->errorValue = ev->u.u.type; + return BadValue; + } + } + if (ev->u.keyButtonPointer.time) { + TimeStamp activateTime; + + CARD32 ms; + + activateTime = currentTime; + ms = activateTime.milliseconds + ev->u.keyButtonPointer.time; + if (ms < activateTime.milliseconds) + activateTime.months++; + activateTime.milliseconds = ms; + ev->u.keyButtonPointer.time = 0; + + /* see mbuf.c:QueueDisplayRequest for code similar to this */ + + if (!ClientSleepUntil(client, &activateTime, NULL, NULL)) { + return BadAlloc; + } + /* swap the request back so we can simply re-execute it */ + if (client->swapped) { + (void) XTestSwapFakeInput(client, (xReq *) stuff); + swaps(&stuff->length); + } + ResetCurrentRequest(client); + client->sequence--; + return Success; + } + switch (type) { + case KeyPress: + case KeyRelease: + dev = (DeviceIntPtr) LookupKeyboardDevice(); + if (ev->u.u.detail < dev->key->curKeySyms.minKeyCode || + ev->u.u.detail > dev->key->curKeySyms.maxKeyCode) { + client->errorValue = ev->u.u.detail; + return BadValue; + } + break; + case MotionNotify: + dev = (DeviceIntPtr) LookupPointerDevice(); + if (ev->u.keyButtonPointer.root == None) + root = GetCurrentRootWindow(); + else { + root = LookupWindow(ev->u.keyButtonPointer.root, client); + if (!root) + return BadWindow; + if (root->parent) { + client->errorValue = ev->u.keyButtonPointer.root; + return BadValue; + } + } + if (ev->u.u.detail == xTrue) { + int x, y; + + GetSpritePosition(&x, &y); + ev->u.keyButtonPointer.rootX += x; + ev->u.keyButtonPointer.rootY += y; + } + else if (ev->u.u.detail != xFalse) { + client->errorValue = ev->u.u.detail; + return BadValue; + } + + + if (ev->u.keyButtonPointer.rootX < 0) + ev->u.keyButtonPointer.rootX = 0; + else if (ev->u.keyButtonPointer.rootX >= root->drawable.width) + ev->u.keyButtonPointer.rootX = root->drawable.width - 1; + if (ev->u.keyButtonPointer.rootY < 0) + ev->u.keyButtonPointer.rootY = 0; + else if (ev->u.keyButtonPointer.rootY >= root->drawable.height) + ev->u.keyButtonPointer.rootY = root->drawable.height - 1; + + if (root != GetCurrentRootWindow()) + { + NewCurrentScreen(root->drawable.pScreen, + ev->u.keyButtonPointer.rootX, + ev->u.keyButtonPointer.rootY); + return client->noClientException; + } + (*root->drawable.pScreen->SetCursorPosition) + (root->drawable.pScreen, + ev->u.keyButtonPointer.rootX, ev->u.keyButtonPointer.rootY, FALSE); + break; + case ButtonPress: + case ButtonRelease: + dev = (DeviceIntPtr) LookupPointerDevice(); + if (!ev->u.u.detail || ev->u.u.detail > dev->button->numButtons) { + client->errorValue = ev->u.u.detail; + return BadValue; + } + break; + } + if (screenIsSaved == SCREEN_SAVER_ON) + SaveScreens(SCREEN_SAVER_OFF, ScreenSaverReset); + ev->u.keyButtonPointer.time = currentTime.milliseconds; + (*dev->public.processInputProc) (ev, dev, nev); + return client->noClientException; +} + +static int +ProcXTestGrabControl(client) +ClientPtr client; +{ + REQUEST(xXTestGrabControlReq); + + REQUEST_SIZE_MATCH(xXTestGrabControlReq); + if ((stuff->impervious != xTrue) && (stuff->impervious != xFalse)) { + client->errorValue = stuff->impervious; + return (BadValue); + } + if (stuff->impervious) + MakeClientGrabImpervious(client); + else + MakeClientGrabPervious(client); + return (client->noClientException); +} + +static int +ProcXTestDispatch(client) +ClientPtr client; +{ + REQUEST(xReq); + switch (stuff->data) { + case X_XTestGetVersion: + return ProcXTestGetVersion(client); + case X_XTestCompareCursor: + return ProcXTestCompareCursor(client); + case X_XTestFakeInput: + return ProcXTestFakeInput(client); + case X_XTestGrabControl: + return ProcXTestGrabControl(client); + default: + return BadRequest; + } +} + +static int +SProcXTestGetVersion(client) +ClientPtr client; +{ + + REQUEST(xXTestGetVersionReq); + + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xXTestGetVersionReq); + swaps(&stuff->minorVersion); + return ProcXTestGetVersion(client); +} + +static int +SProcXTestCompareCursor(client) +ClientPtr client; +{ + + REQUEST(xXTestCompareCursorReq); + + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xXTestCompareCursorReq); + swapl(&stuff->window); + swapl(&stuff->cursor); + return ProcXTestCompareCursor(client); +} + +static int +XTestSwapFakeInput(client, req) +ClientPtr client; + +xReq *req; +{ + int nev; + + xEvent *ev; + + xEvent sev; + + EventSwapPtr proc; + + nev = ((req->length << 2) - sizeof(xReq)) / sizeof(xEvent); + for (ev = (xEvent *) &req[1]; --nev >= 0; ev++) { + /* Swap event */ + proc = EventSwapVector[ev->u.u.type & 0177]; + /* no swapping proc; invalid event type? */ + if (!proc || proc == NotImplemented) { + client->errorValue = ev->u.u.type; + return BadValue; + } + (*proc) (ev, &sev); + *ev = sev; + } + return Success; +} + +static int +SProcXTestFakeInput(client) +ClientPtr client; +{ + + REQUEST(xReq); + + swaps(&stuff->length); + int n = XTestSwapFakeInput(client, stuff); + if (n != Success) + return n; + return ProcXTestFakeInput(client); +} + +static int +SProcXTestGrabControl(client) +ClientPtr client; +{ + + REQUEST(xXTestGrabControlReq); + + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xXTestGrabControlReq); + return ProcXTestGrabControl(client); +} + +static int +SProcXTestDispatch(client) +ClientPtr client; +{ + REQUEST(xReq); + switch (stuff->data) { + case X_XTestGetVersion: + return SProcXTestGetVersion(client); + case X_XTestCompareCursor: + return SProcXTestCompareCursor(client); + case X_XTestFakeInput: + return SProcXTestFakeInput(client); + case X_XTestGrabControl: + return SProcXTestGrabControl(client); + default: + return BadRequest; + } +} diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 0000000..a4fa9a2 --- /dev/null +++ b/autogen.sh @@ -0,0 +1,10 @@ +#! /bin/sh + +srcdir=`dirname $0` +test -z "$srcdir" && srcdir=. + +ORIGDIR=`pwd` +cd $srcdir + +autoreconf -v --install || exit 1 +cd $ORIGDIR || exit $? diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..3ea5d6b --- /dev/null +++ b/configure.ac @@ -0,0 +1,687 @@ +dnl Copyright © 2003-2005 Keith Packard, Daniel Stone +dnl Copyright © 2013 Lauri Kasanen +dnl +dnl Permission to use, copy, modify, distribute, and sell this software and its +dnl documentation for any purpose is hereby granted without fee, provided that +dnl the above copyright notice appear in all copies and that both that +dnl copyright notice and this permission notice appear in supporting +dnl documentation, and that the names of Keith Packard and Daniel Stone not be +dnl used in advertising or publicity pertaining to distribution of the software +dnl without specific, written prior permission. Keith Packard and Daniel Stone +dnl make no representations about the suitability of this software for any +dnl purpose. It is provided "as is" without express or implied warranty. +dnl +dnl KEITH PACKARD AND DANIEL STONE DISCLAIM ALL WARRANTIES WITH REGARD TO THIS +dnl SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, +dnl IN NO EVENT SHALL KEITH PACKARD OR DANIEL STONE BE LIABLE FOR ANY SPECIAL, +dnl INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +dnl LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +dnl OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +dnl PERFORMANCE OF THIS SOFTWARE. +dnl +dnl Process this file with autoconf to create configure. + +AC_PREREQ(2.57) +AC_INIT([tinyx], 1.0) +AC_CONFIG_SRCDIR([Makefile.am]) +AC_CONFIG_MACRO_DIR([m4]) +AM_INIT_AUTOMAKE([dist-bzip2 no-dist-gzip foreign -Wall]) + +dnl this gets generated by autoheader, and thus contains all the defines. we +dnl don't ever actually use it, internally. +AC_CONFIG_HEADERS(include/do-not-use-config.h) +dnl dix-config.h covers most of the DIX (i.e. everything but the DDX, not just +dnl dix/). +AC_CONFIG_HEADERS(include/dix-config.h) +dnl kdrive-config.h covers the kdrive DDX +AC_CONFIG_HEADERS(include/kdrive-config.h) + +AC_PROG_CC +AM_PROG_AS +AC_PROG_INSTALL +AC_PROG_LN_S +AC_DISABLE_SHARED +AC_PROG_LIBTOOL +PKG_PROG_PKG_CONFIG +AC_PROG_LEX +AC_PROG_YACC +XORG_PROG_RAWCPP + +AC_HEADER_DIRENT +AC_HEADER_STDC +AC_CHECK_HEADERS([fcntl.h stdlib.h string.h unistd.h]) + +dnl Checks for typedefs, structures, and compiler characteristics. +AC_C_CONST +AC_C_BIGENDIAN([ENDIAN="X_BIG_ENDIAN"], [ENDIAN="X_LITTLE_ENDIAN"]) + +AC_CHECK_SIZEOF([unsigned long]) +if test "$ac_cv_sizeof_unsigned_long" = 8; then + AC_DEFINE(_XSERVER64, 1, [Define to 1 if unsigned long is 64 bits.]) +fi + +AC_TYPE_PID_T + +dnl Checks for library functions. +AC_FUNC_VPRINTF +AC_CHECK_FUNCS([geteuid getuid link memmove memset mkstemp strchr strrchr \ + strtol getopt getopt_long vsnprintf]) +AC_FUNC_ALLOCA +dnl Old HAS_* names used in os/*.c. +AC_CHECK_FUNC([getdtablesize], + AC_DEFINE(HAS_GETDTABLESIZE, 1, [Have the `getdtablesize' function.])) +AC_CHECK_FUNC([getifaddrs], + AC_DEFINE(HAS_GETIFADDRS, 1, [Have the `getifaddrs' function.])) +AC_CHECK_FUNC([getpeereid], + AC_DEFINE(HAS_GETPEEREID, 1, [Have the `getpeereid' function.])) +AC_CHECK_FUNC([getpeerucred], + AC_DEFINE(HAS_GETPEERUCRED, 1, [Have the `getpeerucred' function.])) +AC_CHECK_FUNC([strlcat], HAVE_STRLCAT=yes, HAVE_STRLCAT=no) +AM_CONDITIONAL(NEED_STRLCAT, [test x$HAVE_STRLCAT = xno]) + +AM_CONDITIONAL(NEED_VSNPRINTF, [test x$HAVE_VSNPRINTF = xno]) + +dnl Check for mmap support for Xvfb +AC_CHECK_FUNC([mmap], AC_DEFINE(HAS_MMAP, 1, [Have the `mmap' function.])) + +dnl Find the math libary +AC_CHECK_LIB(m, sqrt) + +dnl APM header +AC_CHECK_HEADERS([linux/apm_bios.h], LNXAPM=yes) +AM_CONDITIONAL(LNXAPM, [test "x$LNXAPM" = xyes]) + +dnl fbdev header +AC_CHECK_HEADERS([linux/fb.h], FBDEV=yes) +AM_CONDITIONAL(FBDEVHW, [test "x$FBDEV" = xyes]) + +dnl MTRR header +AC_CHECK_HEADERS([asm/mtrr.h], ac_cv_asm_mtrr_h=yes) +if test "x$ac_cv_asm_mtrr_h" = xyes; then + HAVE_MTRR=yes +fi + +dnl BSD MTRR header +AC_CHECK_HEADERS([sys/memrange.h], ac_cv_memrange_h=yes) +if test "x$ac_cv_memrange_h" = xyes; then + HAVE_MTRR=yes +fi + +if test "x$HAVE_MTRR" = xyes; then + AC_DEFINE(HAS_MTRR_SUPPORT, 1, [MTRR support available]) +fi + +dnl A NetBSD MTRR header +AC_CHECK_HEADERS([machine/mtrr.h], ac_cv_machine_mtrr_h=yes) +if test "x$ac_cv_machine_mtrr_h" = xyes; then + AC_DEFINE(HAS_MTRR_BUILTIN, 1, [Define to 1 if NetBSD built-in MTRR + support is available]) +fi + +dnl FreeBSD kldload support (sys/linker.h) +AC_CHECK_HEADERS([sys/linker.h], + [ac_cv_sys_linker_h=yes], + [ac_cv_sys_linker_h=no], + [#include ]) +AM_CONDITIONAL(FREEBSD_KLDLOAD, [test "x$ac_cv_sys_linker_h" = xyes]) + +AC_CACHE_CHECK([for SYSV IPC], + ac_cv_sysv_ipc, + [AC_TRY_LINK([ +#include +],[ +{ + int id; + id = shmget(IPC_PRIVATE, 512, SHM_W | SHM_R); + if (id < 0) return -1; + return shmctl(id, IPC_RMID, 0); +}], + [ac_cv_sysv_ipc=yes], + [ac_cv_sysv_ipc=no])]) +if test "x$ac_cv_sysv_ipc" = xyes; then + AC_DEFINE(HAVE_SYSV_IPC, 1, [Define to 1 if SYSV IPC is available]) +fi + +dnl --------------------------------------------------------------------------- +dnl Bus options and CPU capabilities. Replaces logic in +dnl hw/xfree86/os-support/bus/Makefile.am, among others. +dnl --------------------------------------------------------------------------- +DEFAULT_INT10="x86emu" + +dnl Override defaults as needed for specific platforms: + +case $host_cpu in + alpha*) + ALPHA_VIDEO=yes + case $host_os in + *netbsd*) AC_DEFINE(USE_ALPHA_PIO, 1, [NetBSD PIO alpha IO]) ;; + esac + ;; + arm*) + ARM_VIDEO=yes + ;; + i*86) + I386_VIDEO=yes + case $host_os in + *linux*) DEFAULT_INT10=vm86 ;; + *freebsd*) AC_DEFINE(USE_DEV_IO) ;; + *netbsd*) AC_DEFINE(USE_I386_IOPL) + SYS_LIBS=-li386 + ;; + *openbsd*) AC_DEFINE(USE_I386_IOPL) + SYS_LIBS=-li386 + ;; + esac + ;; + powerpc*) + PPC_VIDEO=yes + case $host_os in + *freebsd*) DEFAULT_INT10=stub ;; + esac + ;; + sparc*) + xorg_loader_sparcmuldiv="yes" + SPARC64_VIDEO=yes + BSD_ARCH_SOURCES="sparc64_video.c ioperm_noop.c" + ;; + x86_64*|amd64*) + I386_VIDEO=yes + case $host_os in + *freebsd*) AC_DEFINE(USE_DEV_IO, 1, [BSD /dev/io]) ;; + *netbsd*) AC_DEFINE(USE_I386_IOPL, 1, [BSD i386 iopl]) + SYS_LIBS=-lx86_64 + ;; + *openbsd*) AC_DEFINE(USE_AMD64_IOPL, 1, [BSD AMD64 iopl]) + SYS_LIBS=-lamd64 + ;; + esac + ;; +esac + +dnl BSD *_video.c selection +AM_CONDITIONAL(ALPHA_VIDEO, [test "x$ALPHA_VIDEO" = xyes]) +AM_CONDITIONAL(ARM_VIDEO, [test "x$ARM_VIDEO" = xyes]) +AM_CONDITIONAL(I386_VIDEO, [test "x$I386_VIDEO" = xyes]) +AM_CONDITIONAL(PPC_VIDEO, [test "x$PPC_VIDEO" = xyes]) +AM_CONDITIONAL(SPARC64_VIDEO, [test "x$SPARC64_VIDEO" = xyes]) + +DRI=no +dnl it would be nice to autodetect these *CONS_SUPPORTs +case $host_os in + *freebsd*) + case $host_os in + kfreebsd*-gnu) ;; + *) AC_DEFINE(CSRG_BASED, 1, [System is BSD-like]) ;; + esac + AC_DEFINE(PCCONS_SUPPORT, 1, [System has PC console]) + AC_DEFINE(PCVT_SUPPORT, 1, [System has PCVT console]) + AC_DEFINE(SYSCONS_SUPPORT, 1, [System has syscons console]) + ;; + *netbsd*) + AC_DEFINE(CSRG_BASED, 1, [System is BSD-like]) + AC_DEFINE(PCCONS_SUPPORT, 1, [System has PC console]) + AC_DEFINE(WSCONS_SUPPORT, 1, [System has wscons console]) + ;; + *openbsd*) + AC_DEFINE(CSRG_BASED, 1, [System is BSD-like]) + AC_DEFINE(PCVT_SUPPORT, 1, [System has PC console]) + AC_DEFINE(WSCONS_SUPPORT, 1, [System has wscons console]) + ;; +esac + +OSNAME=`uname -srm` +AC_DEFINE_UNQUOTED(OSNAME, "$OSNAME", + [Define to OS Name string to display for build OS in Xorg log]) + +DEFAULT_VENDOR_NAME="TinyCore Linux" +DEFAULT_VENDOR_NAME_SHORT="TinyCore" +VERSION_MAJOR=1 +VERSION_MINOR=0 +VERSION_PATCH=0 +VERSION_SNAP=0 +RELEASE_DATE="9 Nov 2013" +DEFAULT_VENDOR_WEB="http://tinycorelinux.com" + +m4_ifdef([AS_HELP_STRING], , [m4_define([AS_HELP_STRING], m4_defn([AC_HELP_STRING]))]) + +dnl Build options. +AC_ARG_ENABLE(werror, AS_HELP_STRING([--enable-werror], + [Treat warnings as errors (default: disabled)]), + [WERROR=$enableval], [WERROR=no]) +AC_ARG_ENABLE(debug, AS_HELP_STRING([--enable-debug], + [Enable debugging (default: disabled)]), + [DEBUGGING=$enableval], [DEBUGGING=no]) +AC_ARG_WITH(int10, AS_HELP_STRING([--with-int10=BACKEND], [int10 backend: vm86, x86emu or stub]), + [INT10="$withval"], + [INT10="$DEFAULT_INT10"]) +AC_ARG_WITH(vendor-name, AS_HELP_STRING([--with-vendor-string=VENDOR], + [Vendor string reported by the server]), + [ VENDOR_STRING="$withval" ], + [ VENDOR_STRING="$DEFAULT_VENDOR_NAME" ]) +AC_ARG_WITH(vendor-name-short, AS_HELP_STRING([--with-vendor-string-short=VENDOR], + [Short version of vendor string reported by the server]), + [ VENDOR_STRING_SHORT="$withval" ], + [ VENDOR_STRING_SHORT="$DEFAULT_VENDOR_NAME_SHORT" ]) +AC_ARG_WITH(vendor-web, AS_HELP_STRING([--with-vendor-web=URL], + [Vendor web address reported by the server]), + [ VENDOR_WEB="$withval" ], + [ VENDOR_WEB="$DEFAULT_VENDOR_WEB" ]) +AC_ARG_WITH(builder-addr, AS_HELP_STRING([--with-builder-addr=ADDRESS], + [Builder address (default: xorg@lists.freedesktop.org)]), + [ BUILDERADDR="$withval" ], + [ BUILDERADDR="xorg@lists.freedesktop.org" ]) +AC_ARG_WITH(fontdir, AS_HELP_STRING([--with-fontdir=FONTDIR], [Path to top level dir where fonts are installed (default: ${libdir}/X11/fonts)]), + [ FONTDIR="$withval" ], + [ FONTDIR="${libdir}/X11/fonts" ]) +DEFAULT_FONT_PATH="${FONTDIR}/misc/,${FONTDIR}/TTF/,${FONTDIR}/OTF,${FONTDIR}/Type1/,${FONTDIR}/100dpi/,${FONTDIR}/75dpi/" +AC_ARG_WITH(default-font-path, AS_HELP_STRING([--with-default-font-path=PATH], [Comma separated list of font dirs]), + [ FONTPATH="$withval" ], + [ FONTPATH="${DEFAULT_FONT_PATH}" ]) + +dnl Extensions. +AC_ARG_ENABLE(xres, AS_HELP_STRING([--disable-xres], [Build XRes extension (default: enabled)]), [RES=$enableval], [RES=yes]) +AC_ARG_ENABLE(screensaver, AS_HELP_STRING([--disable-screensaver], [Build ScreenSaver extension (default: enabled)]), [SCREENSAVER=$enableval], [SCREENSAVER=yes]) +AC_ARG_ENABLE(xdmcp, AS_HELP_STRING([--disable-xdmcp], [Build XDMCP extension (default: auto)]), [XDMCP=$enableval], [XDMCP=auto]) +AC_ARG_ENABLE(xdm-auth-1, AS_HELP_STRING([--disable-xdm-auth-1], [Build XDM-Auth-1 extension (default: auto)]), [XDMAUTH=$enableval], [XDMAUTH=auto]) +AC_ARG_ENABLE(dbe, AS_HELP_STRING([--disable-dbe], [Build DBE extension (default: enabled)]), [DBE=$enableval], [DBE=yes]) +AC_ARG_ENABLE(xf86bigfont, AS_HELP_STRING([--disable-xf86bigfont], [Build XF86 Big Font extension (default: enabled)]), [XF86BIGFONT=$enableval], [XF86BIGFONT=yes]) +AC_ARG_ENABLE(dpms, AS_HELP_STRING([--disable-dpms], [Build DPMS extension (default: enabled)]), [DPMSExtension=$enableval], [DPMSExtension=yes]) + +dnl kdrive and its subsystems +AC_ARG_ENABLE(kdrive, AS_HELP_STRING([--enable-kdrive], [Build kdrive servers (default: yes)]), [KDRIVE=$enableval], [KDRIVE=yes]) + + +dnl chown/chmod to be setuid root as part of build +dnl Replaces InstallXserverSetUID in imake +AC_ARG_ENABLE(install-setuid, + AS_HELP_STRING([--enable-install-setuid], + [Install Xorg server as owned by root with setuid bit (default: auto)]), + [SETUID=$enableval], [SETUID=auto]) +AC_MSG_CHECKING([to see if we can install the Xorg server as root]) +if test "x$SETUID" = "xauto" ; then + case $host_os in + darwin*) SETUID="no" ;; + *) + case $host_cpu in + sparc) SETUID="no" ;; + *) SETUID="yes" ;; + esac + esac + if test "x$SETUID" = xyes; then + touch testfile + chown root testfile > /dev/null 2>&1 || SETUID="no" + rm -f testfile + fi +fi +AC_MSG_RESULT([$SETUID]) +AM_CONDITIONAL(INSTALL_SETUID, [test "x$SETUID" = "xyes"]) + +dnl Issue an error if xtrans.m4 was not found and XTRANS_CONNECTION_FLAGS macro +dnl was not expanded, since xorg-server with no transport types is rather useless. +dnl +dnl If you're seeing an error here, be sure you installed the lib/xtrans module +dnl first and if it's not in the default location, that you set the ACLOCAL +dnl environment variable to find it, such as: +dnl ACLOCAL="aclocal -I ${PREFIX}/share/aclocal" +m4_pattern_forbid([^XTRANS_CONNECTION_FLAGS$]) + +# Transport selection macro from xtrans.m4 +XTRANS_CONNECTION_FLAGS + +# Secure RPC detection macro from xtrans.m4 +XTRANS_SECURE_RPC_FLAGS + +AM_CONDITIONAL(INT10_VM86, [test "x$INT10" = xvm86]) +AM_CONDITIONAL(INT10_X86EMU, [test "x$INT10" = xx86emu]) +AM_CONDITIONAL(INT10_STUB, [test "x$INT10" = xstub]) +if test "x$INT10" = xyes; then + dnl VM86 headers + AC_CHECK_HEADERS([sys/vm86.h sys/io.h]) +fi + +dnl --------------------------------------------------------------------------- +dnl Extension section +dnl --------------------------------------------------------------------------- +XEXT_INC='-I$(top_srcdir)/Xext' +XEXT_LIB='$(top_builddir)/Xext/libXext.la' +XEXTXORG_LIB='$(top_builddir)/Xext/libXextbuiltin.la' + +dnl Core modules for most extensions, et al. +REQUIRED_MODULES="[randrproto >= 1.2] renderproto [fixesproto >= 4.0] [damageproto >= 1.1] xcmiscproto xextproto xproto xtrans xf86bigfontproto [scrnsaverproto >= 1.1] bigreqsproto resourceproto fontsproto inputproto [kbproto >= 1.0.3]" +REQUIRED_LIBS="xfont fontenc" + +AM_CONDITIONAL(SCREENSAVER, [test "x$SCREENSAVER" = xyes]) +if test "x$SCREENSAVER" = xyes; then + AC_DEFINE(SCREENSAVER, 1, [Support MIT-SCREEN-SAVER extension]) +fi + +AM_CONDITIONAL(RES, [test "x$RES" = xyes]) +if test "x$RES" = xyes; then + AC_DEFINE(RES, 1, [Support X resource extension]) + REQUIRED_MODULES="$REQUIRED_MODULES resourceproto" +fi + +AM_CONDITIONAL(DBE, [test "x$DBE" = xyes]) +if test "x$DBE" = xyes; then + AC_DEFINE(DBE, 1, [Support DBE extension]) + DBE_LIB='$(top_builddir)/dbe/libdbe.la' +fi + +AM_CONDITIONAL(XF86BIGFONT, [test "x$XF86BIGFONT" = xyes]) +if test "x$XF86BIGFONT" = xyes; then + AC_DEFINE(XF86BIGFONT, 1, [Support XF86 Big font extension]) +fi + +AM_CONDITIONAL(DPMSExtension, [test "x$DPMSExtension" = xyes]) +if test "x$DPMSExtension" = xyes; then + AC_DEFINE(DPMSExtension, 1, [Support DPMS extension]) +fi + +RENDER_LIB='$(top_builddir)/render/librender.la' +RENDER_INC='-I$(top_srcdir)/render' + +RANDR_LIB='$(top_builddir)/randr/librandr.la' +RANDR_INC='-I$(top_srcdir)/randr' + +FIXES_LIB='$(top_builddir)/xfixes/libxfixes.la' +FIXES_INC='-I$(top_srcdir)/xfixes' + +DAMAGE_LIB='$(top_builddir)/damageext/libdamageext.la' +DAMAGE_INC='-I$(top_srcdir)/damageext' +MIEXT_DAMAGE_LIB='$(top_builddir)/miext/damage/libdamage.la' +MIEXT_DAMAGE_INC='-I$(top_srcdir)/miext/damage' + +AC_CHECK_FUNC(strcasecmp, [], AC_DEFINE([NEED_STRCASECMP], 1, + [Do not have `strcasecmp'.])) + +PKG_CHECK_MODULES([XDMCP], [xdmcp], [have_libxdmcp="yes"], [have_libxdmcp="no"]) +if test "x$have_libxdmcp" = xyes; then + AC_CHECK_LIB(Xdmcp, XdmcpWrap, [have_xdmcpwrap="yes"], [have_xdmcpwrap="no"], [$XDMCP_LIBS]) +fi +if test "x$XDMCP" = xauto; then + if test "x$have_libxdmcp" = xyes; then + XDMCP=yes + else + XDMCP=no + fi +fi +if test "x$XDMAUTH" = xauto; then + if test "x$have_libxdmcp" = xyes && test "x$have_xdmcpwrap" = xyes; then + XDMAUTH=yes + else + XDMAUTH=no + fi +fi + +AM_CONDITIONAL(XDMCP, [test "x$XDMCP" = xyes]) +if test "x$XDMCP" = xyes; then + AC_DEFINE(XDMCP, 1, [Support XDM Control Protocol]) + REQUIRED_LIBS="$REQUIRED_LIBS xdmcp" + XDMCP_MODULES="xdmcp" +fi + +AM_CONDITIONAL(XDMAUTH, [test "x$XDMAUTH" = xyes]) +if test "x$XDMAUTH" = xyes; then + AC_DEFINE(HASXDMAUTH,1,[Support XDM-AUTH*-1]) + if ! test "x$XDMCP" = xyes; then + REQUIRED_LIBS="$REQUIRED_LIBS xdmcp" + XDMCP_MODULES="xdmcp" + fi +fi + +VENDOR_RELEASE="((($VERSION_MAJOR) * 10000000) + (($VERSION_MINOR) * 100000) + (($VERSION_PATCH) * 1000) + $VERSION_SNAP)" + +if test $VERSION_SNAP = "0"; then + if test $VERSION_PATCH = "0"; then + VENDOR_VERSION_STRING="${VERSION_MAJOR}.${VERSION_MINOR}" + else + VENDOR_VERSION_STRING="${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}" + fi +else + VENDOR_VERSION_STRING="${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}.${VERSION_SNAP}" +fi + +VENDOR_RELEASE_STRING="Release ${VENDOR_VERSION_STRING}" +VENDOR_MAN_VERSION="Version ${VENDOR_VERSION_STRING}" + +AC_DEFINE_DIR(COMPILEDDEFAULTFONTPATH, FONTPATH, [Default font path]) +AC_DEFINE_DIR(BASE_FONT_PATH, FONTDIR, [Default base font path]) +AC_DEFINE_UNQUOTED(XVENDORNAME, ["$VENDOR_STRING"], [Vendor name]) +AC_DEFINE_UNQUOTED(XVENDORNAMESHORT, ["$VENDOR_STRING_SHORT"], [Short vendor name]) +AC_DEFINE_UNQUOTED(XORG_RELEASE, ["$VENDOR_RELEASE_STRING"], [Vendor release]) +AC_DEFINE_UNQUOTED(XORG_DATE, ["$RELEASE_DATE"], [Vendor release]) +AC_DEFINE_UNQUOTED(XORG_MAN_VERSION, ["$VENDOR_MAN_VERSION"], [Vendor man version]) +AC_DEFINE_UNQUOTED(BUILDERADDR, ["$BUILDERADDR"], [Builder address]) +AC_DEFINE_UNQUOTED(OSNAME, ["$OSNAME"], [Operating System Name]) +AC_SUBST([VENDOR_STRING]) +AC_SUBST([VENDOR_STRING_SHORT]) +AC_SUBST([VENDOR_RELEASE]) +AC_SUBST([VENDOR_MAN_VERSION]) + +AC_DEFINE(SMART_SCHEDULE, 1, [Include time-based scheduler]) +AM_CONDITIONAL(DEBUG, test "x$DEBUGGING" = xyes) + +if ! test "x$DEBUGGING" = xyes; then + AC_DEFINE(NDEBUG, 1, [Disable some debugging code]) +fi + +DIX_LIB='$(top_builddir)/dix/libdix.la' +OS_LIB='$(top_builddir)/os/libos.la' +MI_LIB='$(top_builddir)/mi/libmi.la' +MI_EXT_LIB='$(top_builddir)/mi/libmiext.la' +MI_INC='-I$(top_srcdir)/mi' +FB_LIB='$(top_builddir)/fb/libfb.la' +FB_INC='-I$(top_srcdir)/fb' +MIEXT_SHADOW_INC='-I$(top_srcdir)/miext/shadow' +MIEXT_SHADOW_LIB='$(top_builddir)/miext/shadow/libshadow.la' +CORE_INCS='-I$(top_srcdir)/include -I$(top_builddir)/include' + +PKG_CHECK_MODULES([XSERVERCFLAGS], [$REQUIRED_MODULES $REQUIRED_LIBS]) +PKG_CHECK_MODULES([XSERVERLIBS], [$REQUIRED_LIBS]) + +XSERVER_CFLAGS="${XSERVERCFLAGS_CFLAGS}" +XSERVER_LIBS="${XSERVERLIBS_LIBS} ${SYS_LIBS} -lm" +AC_SUBST([SYS_LIBS]) + +AC_CHECK_FUNCS([clock_gettime], [have_clock_gettime=yes], + [AC_CHECK_LIB([rt], [clock_gettime], [have_clock_gettime=-lrt], + [have_clock_gettime=no])]) + +AC_MSG_CHECKING([for a useful monotonic clock ...]) + +if ! test "x$have_clock_gettime" = xno; then + if ! test "x$have_clock_gettime" = xyes; then + LIBS="$have_clock_gettime" + else + LIBS="" + fi + + AC_RUN_IFELSE([AC_LANG_SOURCE([ +#define _POSIX_C_SOURCE 199309L +#include + +int main(int argc, char *argv[]) { + struct timespec tp; + + if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0) + return 0; + else + return 1; +} + ])], [MONOTONIC_CLOCK=yes], [MONOTONIC_CLOCK=no], + [MONOTONIC_CLOCK="cross compiling"]) +else + MONOTONIC_CLOCK=no +fi + +AC_MSG_RESULT([$MONOTONIC_CLOCK]) + +if test "x$MONOTONIC_CLOCK" = xyes; then + AC_DEFINE(MONOTONIC_CLOCK, 1, [Have monotonic clock from clock_gettime()]) + XSERVER_LIBS="$XSERVER_LIBS $LIBS" +fi + +XSERVER_CFLAGS="$XSERVER_CFLAGS $CORE_INCS $XEXT_INC $DAMAGE_INC $FIXES_INC $MI_INC $MIEXT_SHADOW_INC $MIEXT_LAYER_INC $MIEXT_DAMAGE_INC $RENDER_INC $RANDR_INC $FB_INC" +AC_DEFINE_UNQUOTED(X_BYTE_ORDER,[$ENDIAN],[Endian order]) + +AC_SUBST([XSERVER_LIBS]) + +dnl --------------------------------------------------------------------------- +dnl DDX section. +dnl --------------------------------------------------------------------------- + +# XORG_CORE_LIBS is needed even if you're not building the Xorg DDX +XORG_CORE_LIBS="$DIX_LIB" +AC_SUBST([XORG_CORE_LIBS]) + +xorg_bus_linuxpci=no +xorg_bus_freebsdpci=no +xorg_bus_netbsdpci=no +xorg_bus_ix86pci=no +xorg_bus_ppcpci=no +xorg_bus_sparcpci=no +xorg_bus_sparc=no + +AM_CONDITIONAL([XORG], [test "x$XORG" = xyes]) +AM_CONDITIONAL([XORG_BUS_LINUXPCI], [test "x$xorg_bus_linuxpci" = xyes]) +AM_CONDITIONAL([XORG_BUS_FREEBSDPCI], [test "x$xorg_bus_freebsdpci" = xyes]) +AM_CONDITIONAL([XORG_BUS_NETBSDPCI], [test "x$xorg_bus_netbsdpci" = xyes]) +AM_CONDITIONAL([XORG_BUS_IX86PCI], [test "x$xorg_bus_ix86pci" = xyes]) +AM_CONDITIONAL([XORG_BUS_PPCPCI], [test "x$xorg_bus_ppcpci" = xyes]) +AM_CONDITIONAL([XORG_BUS_SPARCPCI], [test "x$xorg_bus_sparcpci" = xyes]) +AM_CONDITIONAL([XORG_BUS_SPARC], [test "x$xorg_bus_sparc" = xyes]) +AM_CONDITIONAL([XORG_LOADER_SPARC], [test "x$xorg_loader_sparcmuldiv" = xyes]) +AM_CONDITIONAL([LINUX_IA64], [test "x$linux_ia64" = xyes]) +AM_CONDITIONAL([LINUX_ALPHA], [test "x$linux_alpha" = xyes]) +AM_CONDITIONAL([LNXACPI], [test "x$linux_acpi" = xyes]) + +dnl kdrive DDX + +AM_CONDITIONAL(KDRIVE, [test x$KDRIVE = xyes]) +if test "$KDRIVE" = yes; then + AC_DEFINE(KDRIVESERVER,1,[Build Kdrive X server]) + AC_DEFINE(KDRIVEDDXACTIONS,,[Build kdrive ddx]) + + AC_CHECK_HEADERS([asm/vm86.h sys/io.h]) + if test "$ac_cv_header_asm_vm86_h" = yes; then + AC_DEFINE(KDRIVEVESA, 1, [Build VESA-based kdrive servers]) + fi + + AC_CHECK_HEADERS([linux/fb.h]) + if test "$ac_cv_header_linux_fb_h" = yes; then + AC_DEFINE(KDRIVEFBDEV, 1, [Build fbdev-based kdrive server]) + fi + + # damage shadow extension fb mi + KDRIVE_INC='-I$(top_srcdir)/kdrive/src' + KDRIVE_PURE_INCS="$KDRIVE_INC $MIEXT_DAMAGE_INC $MIEXT_SHADOW_INC $XEXT_INC $FB_INC $MI_INC" + KDRIVE_OS_INC='-I$(top_srcdir)/kdrive/linux' + KDRIVE_INCS="$KDRIVE_PURE_INCS $KDRIVE_OS_INC" + + KDRIVE_CFLAGS="$XSERVER_CFLAGS -DHAVE_KDRIVE_CONFIG_H" + + # dix os fb mi extension glx (NOTYET) damage shadow + #KDRIVE_PURE_LIBS="$DIX_LIB $OS_LIB $FB_LIB $XEXT_LIB $MIEXT_DAMAGE_LIB \ + # $MIEXT_SHADOW_LIB" + KDRIVE_PURE_LIBS="$FB_LIB $MI_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $RENDER_LIB $RANDR_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $OS_LIB" + KDRIVE_LIB='$(top_builddir)/kdrive/src/libkdrive.a' + case $host_os in + *linux*) + KDRIVE_OS_LIB='$(top_builddir)/kdrive/linux/liblinux.a' + KDRIVELINUX=yes + ;; + esac + KDRIVE_STUB_LIB='$(top_builddir)/kdrive/src/libkdrivestubs.a' + KDRIVE_LIBS="$DIX_LIB $KDRIVE_LIB $KDRIVE_OS_LIB $KDRIVE_PURE_LIBS $KDRIVE_STUB_LIB" +fi +AC_SUBST(KDRIVE_INCS) +AC_SUBST(KDRIVE_PURE_INCS) +AC_SUBST(KDRIVE_CFLAGS) +AC_SUBST(KDRIVE_PURE_LIBS) +AC_SUBST(KDRIVE_LIBS) +AM_CONDITIONAL(KDRIVELINUX, [test "x$KDRIVELINUX" = xyes]) +AM_CONDITIONAL(KDRIVEVESA, [test x"$ac_cv_header_asm_vm86_h" = xyes]) +AM_CONDITIONAL(KDRIVEFBDEV, [test x"$ac_cv_header_linux_fb_h" = xyes]) + +dnl and the rest of these are generic, so they're in config.h +AC_DEFINE(XResExtension, 1, [Build XRes extension]) + +AC_TRY_COMPILE([ +#include +#ifndef __GLIBC__ +#error not glibc +#endif +], [], [AC_DEFINE(_GNU_SOURCE, 1, + [ Enable GNU and other extensions to the C environment for glibc])]) + +dnl ---------- Compiler arguments + +AX_CHECK_COMPILE_FLAG([-flto], + [CFLAGS="$CFLAGS -flto"; LDFLAGS="$LDFLAGS -flto"; ac_cv_lto_supported=yes], + [ac_cv_lto_supported=no], + []) + +if test x"$ac_cv_lto_supported" = xno; then + AC_MSG_NOTICE([LTO not supported, checking sections instead...]) + + AX_CHECK_COMPILE_FLAG([-ffunction-sections], + [CFLAGS="$CFLAGS -ffunction-sections -fdata-sections" + LDFLAGS="$LDFLAGS -Wl,-gc-sections" + ac_cv_sections_supported=yes], + [ac_cv_sections_supported=no], + []) +fi + +AX_CHECK_COMPILE_FLAG([-fvisibility=hidden], + [CFLAGS="$CFLAGS -fvisibility=hidden"; ac_cv_visibility_supported=yes], + [ac_cv_visiblity_supported=no], + []) + +AX_CHECK_LINK_FLAG([-Wl,-as-needed], [LDFLAGS="$LDFLAGS -Wl,-as-needed"], + [], []) + +dnl ---------- + +AC_CHECK_LIB([ife],[meaning]) + +CFLAGS="$XSERVER_CFLAGS $CFLAGS -Wall" +AC_SUBST([CFLAGS]) + +LDFLAGS="$LDFLAGS -Wl,-O1" +AC_SUBST([LDFLAGS]) + +BUILD_DATE="$(date +'%Y%m%d')" +AC_SUBST([BUILD_DATE]) + +DIX_CFLAGS="-DHAVE_DIX_CONFIG_H" +AC_SUBST([DIX_CFLAGS]) + +AC_SUBST([libdir]) +AC_SUBST([exec_prefix]) +AC_SUBST([prefix]) + +# XORG in this case refers to the roll-up releases, not the Xorg DDX. +XORG_RELEASE_VERSION + +AC_OUTPUT([ +Makefile +include/Makefile +damageext/Makefile +dbe/Makefile +dix/Makefile +fb/Makefile +mi/Makefile +miext/Makefile +miext/damage/Makefile +miext/shadow/Makefile +os/Makefile +randr/Makefile +render/Makefile +Xext/Makefile +xfixes/Makefile +kdrive/Makefile +kdrive/fbdev/Makefile +kdrive/linux/Makefile +kdrive/src/Makefile +kdrive/vesa/Makefile +]) diff --git a/damageext/Makefile.am b/damageext/Makefile.am new file mode 100644 index 0000000..35f7620 --- /dev/null +++ b/damageext/Makefile.am @@ -0,0 +1,8 @@ +noinst_LTLIBRARIES = libdamageext.la + +AM_CFLAGS = $(DIX_CFLAGS) + +libdamageext_la_SOURCES = \ + damageext.c \ + damageext.h \ + damageextint.h diff --git a/damageext/damageext.c b/damageext/damageext.c new file mode 100644 index 0000000..3c34ebc --- /dev/null +++ b/damageext/damageext.c @@ -0,0 +1,515 @@ +/* + * Copyright © 2002 Keith Packard + * + * 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, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "damageextint.h" +#include "extinit.h" + +unsigned char DamageReqCode; + +int DamageEventBase; + +int DamageErrorBase; + +int DamageClientPrivateIndex; + +RESTYPE DamageExtType; + +RESTYPE DamageExtWinType; + +/* Version of the damage extension supported by the server, as opposed to the + * DAMAGE_* defines from damageproto for what version the proto header + * supports. + */ +#define SERVER_DAMAGE_MAJOR 1 +#define SERVER_DAMAGE_MINOR 1 + +#define prScreen screenInfo.screens[0] + +static void +DamageExtNotify(DamageExtPtr pDamageExt, BoxPtr pBoxes, int nBoxes) +{ + ClientPtr pClient = pDamageExt->pClient; + DamageClientPtr pDamageClient = GetDamageClient(pClient); + DrawablePtr pDrawable = pDamageExt->pDrawable; + xDamageNotifyEvent ev; + int i; + + UpdateCurrentTimeIf(); + ev = (xDamageNotifyEvent) { + .type = DamageEventBase + XDamageNotify, + .level = pDamageExt->level, + .drawable = pDamageExt->drawable, + .damage = pDamageExt->id, + .timestamp = currentTime.milliseconds, + .geometry.x = pDrawable->x, + .geometry.y = pDrawable->y, + .geometry.width = pDrawable->width, + .geometry.height = pDrawable->height + }; + if (pBoxes) { + for (i = 0; i < nBoxes; i++) { + ev.level = pDamageExt->level; + if (i < nBoxes - 1) + ev.level |= DamageNotifyMore; + ev.area.x = pBoxes[i].x1; + ev.area.y = pBoxes[i].y1; + ev.area.width = pBoxes[i].x2 - pBoxes[i].x1; + ev.area.height = pBoxes[i].y2 - pBoxes[i].y1; + WriteEventsToClient(pClient, 1, (xEvent *) &ev); + } + } + else { + ev.area.x = 0; + ev.area.y = 0; + ev.area.width = pDrawable->width; + ev.area.height = pDrawable->height; + WriteEventsToClient(pClient, 1, (xEvent *) &ev); + } + /* Composite extension marks clients with manual Subwindows as critical */ + if (pDamageClient->critical > 0) { + SetCriticalOutputPending(); + pClient->smart_priority = SMART_MAX_PRIORITY; + } +} + +static void +DamageExtReport(DamagePtr pDamage, RegionPtr pRegion, void *closure) +{ + DamageExtPtr pDamageExt = closure; + + switch (pDamageExt->level) { + case DamageReportRawRegion: + case DamageReportDeltaRegion: + DamageExtNotify(pDamageExt, REGION_RECTS(pRegion), + REGION_NUM_RECTS(pRegion)); + break; + case DamageReportBoundingBox: + DamageExtNotify(pDamageExt, REGION_EXTENTS(pRegion), 1); + break; + case DamageReportNonEmpty: + DamageExtNotify(pDamageExt, NullBox, 0); + break; + case DamageReportNone: + break; + } +} + +static void +DamageExtDestroy(DamagePtr pDamage, void *closure) +{ + DamageExtPtr pDamageExt = closure; + + pDamageExt->pDamage = 0; + if (pDamageExt->id) + FreeResource(pDamageExt->id, RT_NONE); +} + +void +DamageExtSetCritical(ClientPtr pClient, Bool critical) +{ + DamageClientPtr pDamageClient = GetDamageClient(pClient); + + if (pDamageClient) + pDamageClient->critical += critical ? 1 : -1; +} + +static int +ProcDamageQueryVersion(ClientPtr client) +{ + DamageClientPtr pDamageClient = GetDamageClient(client); + + xDamageQueryVersionReply rep; + + + REQUEST(xDamageQueryVersionReq); + + REQUEST_SIZE_MATCH(xDamageQueryVersionReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + if (stuff->majorVersion < SERVER_DAMAGE_MAJOR) { + rep.majorVersion = stuff->majorVersion; + rep.minorVersion = stuff->minorVersion; + } + else { + rep.majorVersion = SERVER_DAMAGE_MAJOR; + if (stuff->majorVersion == SERVER_DAMAGE_MAJOR && + stuff->minorVersion < SERVER_DAMAGE_MINOR) + rep.minorVersion = stuff->minorVersion; + else + rep.minorVersion = SERVER_DAMAGE_MINOR; + } + pDamageClient->major_version = rep.majorVersion; + pDamageClient->minor_version = rep.minorVersion; + if (client->swapped) { + swaps(&rep.sequenceNumber); + swapl(&rep.length); + swapl(&rep.majorVersion); + swapl(&rep.minorVersion); + } + WriteToClient(client, sizeof(xDamageQueryVersionReply), (char *) &rep); + return (client->noClientException); +} + +static int +ProcDamageCreate(ClientPtr client) +{ + DrawablePtr pDrawable; + DamageExtPtr pDamageExt; + DamageReportLevel level; + RegionPtr pRegion; + + REQUEST(xDamageCreateReq); + + REQUEST_SIZE_MATCH(xDamageCreateReq); + LEGAL_NEW_RESOURCE(stuff->damage, client); + SECURITY_VERIFY_DRAWABLE(pDrawable, stuff->drawable, client, + SecurityReadAccess); + switch (stuff->level) { + case XDamageReportRawRectangles: + level = DamageReportRawRegion; + break; + case XDamageReportDeltaRectangles: + level = DamageReportDeltaRegion; + break; + case XDamageReportBoundingBox: + level = DamageReportBoundingBox; + break; + case XDamageReportNonEmpty: + level = DamageReportNonEmpty; + break; + default: + client->errorValue = stuff->level; + return BadValue; + } + + pDamageExt = malloc(sizeof(DamageExtRec)); + if (!pDamageExt) + return BadAlloc; + pDamageExt->id = stuff->damage; + pDamageExt->pDrawable = pDrawable; + pDamageExt->level = level; + pDamageExt->pClient = client; + pDamageExt->pDamage = DamageCreate(DamageExtReport, + DamageExtDestroy, + level, + FALSE, pDrawable->pScreen, pDamageExt); + if (!pDamageExt->pDamage) { + free(pDamageExt); + return BadAlloc; + } + if (!AddResource(stuff->damage, DamageExtType, (pointer) pDamageExt)) + return BadAlloc; + + DamageRegister(pDamageExt->pDrawable, pDamageExt->pDamage); + + if (pDrawable->type == DRAWABLE_WINDOW) { + pRegion = &((WindowPtr) pDrawable)->borderClip; + DamageDamageRegion(pDrawable, pRegion); + } + + return (client->noClientException); +} + +static int +ProcDamageDestroy(ClientPtr client) +{ + REQUEST(xDamageDestroyReq); + DamageExtPtr pDamageExt; + + REQUEST_SIZE_MATCH(xDamageDestroyReq); + VERIFY_DAMAGEEXT(pDamageExt, stuff->damage, client, SecurityWriteAccess); + FreeResource(stuff->damage, RT_NONE); + return (client->noClientException); +} + +static int +ProcDamageSubtract(ClientPtr client) +{ + REQUEST(xDamageSubtractReq); + DamageExtPtr pDamageExt; + + RegionPtr pRepair; + + RegionPtr pParts; + + REQUEST_SIZE_MATCH(xDamageSubtractReq); + VERIFY_DAMAGEEXT(pDamageExt, stuff->damage, client, SecurityWriteAccess); + VERIFY_REGION_OR_NONE(pRepair, stuff->repair, client, SecurityWriteAccess); + VERIFY_REGION_OR_NONE(pParts, stuff->parts, client, SecurityWriteAccess); + + if (pDamageExt->level != DamageReportRawRegion) { + DamagePtr pDamage = pDamageExt->pDamage; + + if (pRepair) { + if (pParts) + REGION_INTERSECT(pParts, DamageRegion(pDamage), + pRepair); + if (DamageSubtract(pDamage, pRepair)) + DamageExtReport(pDamage, DamageRegion(pDamage), + (void *) pDamageExt); + } + else { + if (pParts) + REGION_COPY(pParts, DamageRegion(pDamage)); + DamageEmpty(pDamage); + } + } + return (client->noClientException); +} + +static int +ProcDamageAdd(ClientPtr client) +{ + REQUEST(xDamageAddReq); + DrawablePtr pDrawable; + + RegionPtr pRegion; + + REQUEST_SIZE_MATCH(xDamageAddReq); + VERIFY_REGION(pRegion, stuff->region, client, SecurityWriteAccess); + SECURITY_VERIFY_DRAWABLE(pDrawable, stuff->drawable, client, + SecurityReadAccess); + + /* The region is relative to the drawable origin, so translate it out to + * screen coordinates like damage expects. + */ + REGION_TRANSLATE(pRegion, pDrawable->x, pDrawable->y); + DamageDamageRegion(pDrawable, pRegion); + REGION_TRANSLATE(pRegion, -pDrawable->x, -pDrawable->y); + + return (client->noClientException); +} + +/* Major version controls available requests */ +static const int version_requests[] = { + X_DamageQueryVersion, /* before client sends QueryVersion */ + X_DamageAdd, /* Version 1 */ +}; + +#define NUM_VERSION_REQUESTS (sizeof (version_requests) / sizeof (version_requests[0])) + +int (*ProcDamageVector[XDamageNumberRequests]) (ClientPtr) = { +/*************** Version 1 ******************/ + ProcDamageQueryVersion, + ProcDamageCreate, ProcDamageDestroy, ProcDamageSubtract, +/*************** Version 1.1 ****************/ +ProcDamageAdd,}; + +static int +ProcDamageDispatch(ClientPtr client) +{ + REQUEST(xDamageReq); + DamageClientPtr pDamageClient = GetDamageClient(client); + + if (pDamageClient->major_version >= NUM_VERSION_REQUESTS) + return BadRequest; + if (stuff->damageReqType > version_requests[pDamageClient->major_version]) + return BadRequest; + return (*ProcDamageVector[stuff->damageReqType]) (client); +} + +static int +SProcDamageQueryVersion(ClientPtr client) +{ + + REQUEST(xDamageQueryVersionReq); + + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xDamageQueryVersionReq); + swapl(&stuff->majorVersion); + swapl(&stuff->minorVersion); + return (*ProcDamageVector[stuff->damageReqType]) (client); +} + +static int +SProcDamageCreate(ClientPtr client) +{ + + REQUEST(xDamageCreateReq); + + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xDamageCreateReq); + swapl(&stuff->damage); + swapl(&stuff->drawable); + return (*ProcDamageVector[stuff->damageReqType]) (client); +} + +static int +SProcDamageDestroy(ClientPtr client) +{ + + REQUEST(xDamageDestroyReq); + + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xDamageDestroyReq); + swapl(&stuff->damage); + return (*ProcDamageVector[stuff->damageReqType]) (client); +} + +static int +SProcDamageSubtract(ClientPtr client) +{ + + REQUEST(xDamageSubtractReq); + + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xDamageSubtractReq); + swapl(&stuff->damage); + swapl(&stuff->repair); + swapl(&stuff->parts); + return (*ProcDamageVector[stuff->damageReqType]) (client); +} + +static int +SProcDamageAdd(ClientPtr client) +{ + + REQUEST(xDamageAddReq); + + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xDamageSubtractReq); + swapl(&stuff->drawable); + swapl(&stuff->region); + return (*ProcDamageVector[stuff->damageReqType]) (client); +} + +int (*SProcDamageVector[XDamageNumberRequests]) (ClientPtr) = { +/*************** Version 1 ******************/ + SProcDamageQueryVersion, + SProcDamageCreate, SProcDamageDestroy, SProcDamageSubtract, +/*************** Version 1.1 ****************/ +SProcDamageAdd,}; + +static int +SProcDamageDispatch(ClientPtr client) +{ + REQUEST(xDamageReq); + if (stuff->damageReqType >= XDamageNumberRequests) + return BadRequest; + return (*SProcDamageVector[stuff->damageReqType]) (client); +} + +static void +DamageClientCallback(CallbackListPtr *list, pointer closure, pointer data) +{ + NewClientInfoRec *clientinfo = (NewClientInfoRec *) data; + ClientPtr pClient = clientinfo->client; + DamageClientPtr pDamageClient = GetDamageClient(pClient); + + pDamageClient->critical = 0; + pDamageClient->major_version = 0; + pDamageClient->minor_version = 0; +} + + /*ARGSUSED*/ static void +DamageResetProc(ExtensionEntry * extEntry) +{ + DeleteCallback(&ClientStateCallback, DamageClientCallback, 0); +} + +static int +FreeDamageExt(pointer value, XID did) +{ + DamageExtPtr pDamageExt = (DamageExtPtr) value; + + /* + * Get rid of the resource table entry hanging from the window id + */ + pDamageExt->id = 0; + if (WindowDrawable(pDamageExt->pDrawable->type)) + FreeResourceByType(pDamageExt->pDrawable->id, DamageExtWinType, TRUE); + if (pDamageExt->pDamage) { + DamageUnregister(pDamageExt->pDrawable, pDamageExt->pDamage); + DamageDestroy(pDamageExt->pDamage); + } + free(pDamageExt); + return Success; +} + +static int +FreeDamageExtWin(pointer value, XID wid) +{ + DamageExtPtr pDamageExt = (DamageExtPtr) value; + + if (pDamageExt->id) + FreeResource(pDamageExt->id, RT_NONE); + return Success; +} + +void +SDamageNotifyEvent(xDamageNotifyEvent * from, xDamageNotifyEvent * to) +{ + to->type = from->type; + cpswaps(from->sequenceNumber, to->sequenceNumber); + cpswapl(from->drawable, to->drawable); + cpswapl(from->damage, to->damage); + cpswaps(from->area.x, to->area.x); + cpswaps(from->area.y, to->area.y); + cpswaps(from->area.width, to->area.width); + cpswaps(from->area.height, to->area.height); + cpswaps(from->geometry.x, to->geometry.x); + cpswaps(from->geometry.y, to->geometry.y); + cpswaps(from->geometry.width, to->geometry.width); + cpswaps(from->geometry.height, to->geometry.height); +} + +void +DamageExtensionInit(void) +{ + ExtensionEntry *extEntry; + + int s; + + for (s = 0; s < screenInfo.numScreens; s++) + DamageSetup(screenInfo.screens[s]); + + DamageExtType = CreateNewResourceType(FreeDamageExt); + if (!DamageExtType) + return; + + DamageExtWinType = CreateNewResourceType(FreeDamageExtWin); + if (!DamageExtWinType) + return; + + DamageClientPrivateIndex = AllocateClientPrivateIndex(); + if (!AllocateClientPrivate(DamageClientPrivateIndex, + sizeof(DamageClientRec))) + return; + if (!AddCallback(&ClientStateCallback, DamageClientCallback, 0)) + return; + + if ((extEntry = AddExtension(DAMAGE_NAME, XDamageNumberEvents, + XDamageNumberErrors, + ProcDamageDispatch, SProcDamageDispatch, + DamageResetProc, StandardMinorOpcode)) != 0) { + DamageReqCode = (unsigned char) extEntry->base; + DamageEventBase = extEntry->eventBase; + DamageErrorBase = extEntry->errorBase; + EventSwapVector[DamageEventBase + XDamageNotify] = + (EventSwapPtr) SDamageNotifyEvent; + } +} diff --git a/damageext/damageext.h b/damageext/damageext.h new file mode 100644 index 0000000..bd99635 --- /dev/null +++ b/damageext/damageext.h @@ -0,0 +1,33 @@ +/* + * Copyright © 2002 Keith Packard + * + * 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, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#ifndef _DAMAGEEXT_H_ +#define _DAMAGEEXT_H_ + +void + DamageExtensionInit(void); + +#endif /* _DAMAGEEXT_H_ */ diff --git a/damageext/damageextint.h b/damageext/damageextint.h new file mode 100644 index 0000000..e7beb36 --- /dev/null +++ b/damageext/damageextint.h @@ -0,0 +1,91 @@ +/* + * Copyright © 2002 Keith Packard + * + * 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, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#ifndef _DAMAGEEXTINT_H_ +#define _DAMAGEEXTINT_H_ + +#include +#include +#include "misc.h" +#include "os.h" +#include "dixstruct.h" +#include "extnsionst.h" +#include +#include "windowstr.h" +#include "selection.h" +#include "scrnintstr.h" +#include "damageext.h" +#include "damage.h" +#include "xfixes.h" + +extern unsigned char DamageReqCode; + +extern int DamageEventBase; + +extern int DamageErrorBase; + +extern int DamageClientPrivateIndex; + +extern RESTYPE DamageExtType; + +extern RESTYPE DamageExtWinType; + +typedef struct _DamageClient { + CARD32 major_version; + CARD32 minor_version; + int critical; +} DamageClientRec, *DamageClientPtr; + +#define GetDamageClient(pClient) ((DamageClientPtr) (pClient)->devPrivates[DamageClientPrivateIndex].ptr) + +typedef struct _DamageExt { + DamagePtr pDamage; + DrawablePtr pDrawable; + DamageReportLevel level; + ClientPtr pClient; + XID id; + XID drawable; +} DamageExtRec, *DamageExtPtr; + +extern int (*ProcDamageVector[ /*XDamageNumberRequests */ ]) (ClientPtr); + +extern int (*SProcDamageVector[ /*XDamageNumberRequests */ ]) (ClientPtr); + +#define VERIFY_DAMAGEEXT(pDamageExt, rid, client, mode) { \ + pDamageExt = SecurityLookupIDByType (client, rid, DamageExtType, mode); \ + if (!pDamageExt) { \ + client->errorValue = rid; \ + return DamageErrorBase + BadDamage; \ + } \ +} + +void + SDamageNotifyEvent(xDamageNotifyEvent * from, xDamageNotifyEvent * to); + +void + DamageExtSetCritical(ClientPtr pClient, Bool critical); + +#endif /* _DAMAGEEXTINT_H_ */ diff --git a/dbe/Makefile.am b/dbe/Makefile.am new file mode 100644 index 0000000..d609996 --- /dev/null +++ b/dbe/Makefile.am @@ -0,0 +1,10 @@ +noinst_LTLIBRARIES = libdbe.la + +AM_CFLAGS = $(DIX_CFLAGS) + +libdbe_la_SOURCES = \ + dbe.c \ + dbestruct.h \ + midbe.c \ + midbe.h \ + midbestr.h diff --git a/dbe/dbe.c b/dbe/dbe.c new file mode 100644 index 0000000..2e945be --- /dev/null +++ b/dbe/dbe.c @@ -0,0 +1,1829 @@ +/****************************************************************************** + * + * Copyright (c) 1994, 1995 Hewlett-Packard Company + * + * 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, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * 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 HEWLETT-PACKARD COMPANY 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 Hewlett-Packard + * Company 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 Hewlett-Packard Company. + * + * DIX DBE code + * + *****************************************************************************/ + +/* INCLUDES */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include "scrnintstr.h" +#include "extnsionst.h" +#include "extinit.h" +#include "gcstruct.h" +#include "dixstruct.h" +#define NEED_DBE_PROTOCOL +#include "dbestruct.h" +#include "midbe.h" + +/* GLOBALS */ + +/* Per-screen initialization functions [init'ed by DbeRegisterFunction()] */ +static Bool (*DbeInitFunct[MAXSCREENS]) (); /* pScreen, pDbeScreenPriv */ + +/* These are static globals copied to DBE's screen private for use by DDX */ +static int dbeScreenPrivIndex; + +static int dbeWindowPrivIndex; + +/* These are static globals copied to DBE's screen private for use by DDX */ +static RESTYPE dbeDrawableResType; + +static RESTYPE dbeWindowPrivResType; + +/* This global is used by DbeAllocWinPrivPrivIndex() */ +static int winPrivPrivCount = 0; + +/* Used to generate DBE's BadBuffer error. */ +static int dbeErrorBase; + +/* Used by DbeRegisterFunction() to initialize the initialization function + * table only once per server lifetime. + */ +static Bool firstRegistrationPass = TRUE; + +/****************************************************************************** + * + * DBE DIX Procedure: DbeValidateBuffer + * + * Description: + * + * This function is called from VALIDATE_DRAWABLE_AND_GC and from + * various places in dispatch.c if the server has been compiled with + * the flags -DNEED_DBE_BUF_BITS and -DNEED_DBE_BUF_VALIDATE. + * When pWin->dstBuffer changes, this function will be called with pWin + * as the first argument, the drawable ID that was specified as the + * second argument (could be a back buffer id), and True for the third + * argument. + * When pWin->srcBuffer changes, the third argument will be False, and + * the first two arguments are as described for dstBuffer. + * + * This function should prepare the hardware to access the specified + * buffer for reads (if dstbuf is False) or writes (if dstbuf is True). + * + *****************************************************************************/ + +void +DbeValidateBuffer(WindowPtr pWin, XID drawID, Bool dstbuf) +{ + DbeScreenPrivPtr pDbeScreenPriv = DBE_SCREEN_PRIV_FROM_WINDOW(pWin); + + if (pDbeScreenPriv->ValidateBuffer) + (*pDbeScreenPriv->ValidateBuffer) (pWin, drawID, dstbuf); +} + +/****************************************************************************** + * + * DBE DIX Procedure: DbeRegisterFunction + * + * Description: + * + * This function registers the DBE init function for the specified screen. + * + *****************************************************************************/ + +void +DbeRegisterFunction(ScreenPtr pScreen, Bool (*funct) ( /* ??? */ )) +{ + int i; + + /* Initialize the initialization function table if it has not been + * initialized already. + */ + if (firstRegistrationPass) { + for (i = 0; i < MAXSCREENS; i++) { + DbeInitFunct[i] = NULL; + } + + firstRegistrationPass = FALSE; + } + + DbeInitFunct[pScreen->myNum] = funct; + +} /* DbeRegisterFunction() */ + +/****************************************************************************** + * + * DBE DIX Procedure: DbeAllocWinPriv + * + * Description: + * + * This function was cloned from AllocateWindow() in window.c. + * This function allocates a window priv structure to be associated + * with a double-buffered window. + * + *****************************************************************************/ +static DbeWindowPrivPtr +DbeAllocWinPriv(ScreenPtr pScreen) +{ + DbeWindowPrivPtr pDbeWindowPriv; + + DbeScreenPrivPtr pDbeScreenPriv; + + char *ptr; + + DevUnion *ppriv; + + unsigned int *sizes; + + unsigned int size; + + int i; + + pDbeScreenPriv = DBE_SCREEN_PRIV(pScreen); + pDbeWindowPriv = + malloc(pDbeScreenPriv->totalWinPrivSize); + + if (pDbeWindowPriv) { + ppriv = (DevUnion *) (pDbeWindowPriv + 1); + pDbeWindowPriv->devPrivates = ppriv; + sizes = pDbeScreenPriv->winPrivPrivSizes; + ptr = (char *) (ppriv + pDbeScreenPriv->winPrivPrivLen); + for (i = pDbeScreenPriv->winPrivPrivLen; --i >= 0; ppriv++, sizes++) { + if ((size = *sizes)) { + ppriv->ptr = (pointer) ptr; + ptr += size; + } + else + ppriv->ptr = (pointer) NULL; + } + } + + return (pDbeWindowPriv); + +} /* DbeAllocWinPriv() */ + +/****************************************************************************** + * + * DBE DIX Procedure: DbeFallbackAllocWinPriv + * + * Description: + * + * This is a fallback function for AllocWinPriv(). + * + *****************************************************************************/ + +#if 0 /* NOT USED */ +static DbeWindowPrivPtr +DbeFallbackAllocWinPriv(pScreen) +ScreenPtr pScreen; +{ + return (NULL); +} /* DbeFallbackAllocWinPriv() */ +#endif + +/****************************************************************************** + * + * DBE DIX Procedure: DbeAllocWinPrivPrivIndex + * + * Description: + * + * This function was cloned from AllocateWindowPrivateIndex() in window.c. + * This function allocates a new window priv priv index by simply returning + * an incremented private counter. + * + *****************************************************************************/ + +static int +DbeAllocWinPrivPrivIndex(void) +{ + return winPrivPrivCount++; + +} /* DbeAllocWinPrivPrivIndex() */ + +/****************************************************************************** + * + * DBE DIX Procedure: DbeAllocWinPrivPriv + * + * Description: + * + * This function was cloned from AllocateWindowPrivate() in privates.c. + * This function allocates a private structure to be hung off + * a window private. + * + *****************************************************************************/ + +static Bool +DbeAllocWinPrivPriv(register ScreenPtr pScreen, int index, unsigned int amount) +{ + DbeScreenPrivPtr pDbeScreenPriv; + + unsigned int oldamount; + + pDbeScreenPriv = DBE_SCREEN_PRIV(pScreen); + + if (index >= pDbeScreenPriv->winPrivPrivLen) { + unsigned *nsizes; + + nsizes = (unsigned *) realloc(pDbeScreenPriv->winPrivPrivSizes, + (index + 1) * sizeof(unsigned)); + if (!nsizes) { + return (FALSE); + } + + while (pDbeScreenPriv->winPrivPrivLen <= index) { + nsizes[pDbeScreenPriv->winPrivPrivLen++] = 0; + pDbeScreenPriv->totalWinPrivSize += sizeof(DevUnion); + } + + pDbeScreenPriv->winPrivPrivSizes = nsizes; + } + + oldamount = pDbeScreenPriv->winPrivPrivSizes[index]; + + if (amount > oldamount) { + pDbeScreenPriv->winPrivPrivSizes[index] = amount; + pDbeScreenPriv->totalWinPrivSize += (amount - oldamount); + } + return (TRUE); + +} /* DbeAllocWinPrivPriv() */ + +/****************************************************************************** + * + * DBE DIX Procedure: DbeStubScreen + * + * Description: + * + * This is function stubs the function pointers in the given DBE screen + * private and increments the number of stubbed screens. + * + *****************************************************************************/ + +static void +DbeStubScreen(DbeScreenPrivPtr pDbeScreenPriv, int *nStubbedScreens) +{ + /* Stub DIX. */ + pDbeScreenPriv->SetupBackgroundPainter = NULL; + pDbeScreenPriv->AllocWinPriv = NULL; + pDbeScreenPriv->AllocWinPrivPrivIndex = NULL; + pDbeScreenPriv->AllocWinPrivPriv = NULL; + + /* Do not unwrap PositionWindow nor DestroyWindow. If the DDX + * initialization function failed, we assume that it did not wrap + * PositionWindow. Also, DestroyWindow is only wrapped if the DDX + * initialization function succeeded. + */ + + /* Stub DDX. */ + pDbeScreenPriv->GetVisualInfo = NULL; + pDbeScreenPriv->AllocBackBufferName = NULL; + pDbeScreenPriv->SwapBuffers = NULL; + pDbeScreenPriv->BeginIdiom = NULL; + pDbeScreenPriv->EndIdiom = NULL; + pDbeScreenPriv->WinPrivDelete = NULL; + pDbeScreenPriv->ResetProc = NULL; + pDbeScreenPriv->ValidateBuffer = NULL; + + (*nStubbedScreens)++; + +} /* DbeStubScreen() */ + +/****************************************************************************** + * + * DBE DIX Procedure: ProcDbeGetVersion + * + * Description: + * + * This function is for processing a DbeGetVersion request. + * This request returns the major and minor version numbers of this + * extension. + * + * Return Values: + * + * Success + * + *****************************************************************************/ + +static int +ProcDbeGetVersion(ClientPtr client) +{ + /* REQUEST(xDbeGetVersionReq); */ + xDbeGetVersionReply rep; + + + REQUEST_SIZE_MATCH(xDbeGetVersionReq); + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.majorVersion = DBE_MAJOR_VERSION; + rep.minorVersion = DBE_MINOR_VERSION; + + if (client->swapped) { + swaps(&rep.sequenceNumber); + } + + WriteToClient(client, sizeof(xDbeGetVersionReply), (char *) &rep); + + return (client->noClientException); + +} /* ProcDbeGetVersion() */ + +/****************************************************************************** + * + * DBE DIX Procedure: ProcDbeAllocateBackBufferName + * + * Description: + * + * This function is for processing a DbeAllocateBackBufferName request. + * This request allocates a drawable ID used to refer to the back buffer + * of a window. + * + * Return Values: + * + * BadAlloc - server can not allocate resources + * BadIDChoice - id is out of range for client; id is already in use + * BadMatch - window is not an InputOutput window; + * visual of window is not on list returned by + * DBEGetVisualInfo; + * BadValue - invalid swap action is specified + * BadWindow - window is not a valid window + * Success + * + *****************************************************************************/ + +static int +ProcDbeAllocateBackBufferName(ClientPtr client) +{ + REQUEST(xDbeAllocateBackBufferNameReq); + WindowPtr pWin; + DbeScreenPrivPtr pDbeScreenPriv; + DbeWindowPrivPtr pDbeWindowPriv; + XdbeScreenVisualInfo scrVisInfo; + int i; + Bool visualMatched = FALSE; + xDbeSwapAction swapAction; + VisualID visual; + int status; + + REQUEST_SIZE_MATCH(xDbeAllocateBackBufferNameReq); + + /* The window must be valid. */ + if (!(pWin = SecurityLookupWindow(stuff->window, client, + SecurityWriteAccess))) { + return (BadWindow); + } + + /* The window must be InputOutput. */ + if (pWin->drawable.class != InputOutput) { + return BadMatch; + } + + /* The swap action must be valid. */ + swapAction = stuff->swapAction; /* use local var for performance. */ + if ((swapAction != XdbeUndefined) && + (swapAction != XdbeBackground) && + (swapAction != XdbeUntouched) && (swapAction != XdbeCopied)) { + return BadValue; + } + + /* The id must be in range and not already in use. */ + LEGAL_NEW_RESOURCE(stuff->buffer, client); + + /* The visual of the window must be in the list returned by + * GetVisualInfo. + */ + pDbeScreenPriv = DBE_SCREEN_PRIV_FROM_WINDOW(pWin); + if (!pDbeScreenPriv->GetVisualInfo) + return BadMatch; /* screen doesn't support double buffering */ + + if (!(*pDbeScreenPriv->GetVisualInfo) (pWin->drawable.pScreen, &scrVisInfo)) { + /* GetVisualInfo() failed to allocate visual info data. */ + return BadAlloc; + } + + /* See if the window's visual is on the list. */ + visual = wVisual(pWin); + for (i = 0; (i < scrVisInfo.count) && !visualMatched; i++) { + if (scrVisInfo.visinfo[i].visual == visual) { + visualMatched = TRUE; + } + } + + /* Free what was allocated by the GetVisualInfo() call above. */ + free(scrVisInfo.visinfo); + + if (!visualMatched) { + return BadMatch; + } + + if ((pDbeWindowPriv = DBE_WINDOW_PRIV(pWin)) == NULL) { + /* There is no buffer associated with the window. + * Allocate a window priv. + */ + + if (!(pDbeWindowPriv = + (*pDbeScreenPriv->AllocWinPriv) (pWin->drawable.pScreen))) { + return (BadAlloc); + } + + /* Make the window priv a DBE window priv resource. */ + if (!AddResource(stuff->buffer, dbeWindowPrivResType, + (pointer) pDbeWindowPriv)) { + free(pDbeWindowPriv); + return (BadAlloc); + } + + /* Fill out window priv information. */ + pDbeWindowPriv->pWindow = pWin; + pDbeWindowPriv->width = pWin->drawable.width; + pDbeWindowPriv->height = pWin->drawable.height; + pDbeWindowPriv->x = pWin->drawable.x; + pDbeWindowPriv->y = pWin->drawable.y; + pDbeWindowPriv->nBufferIDs = 0; + + /* Set the buffer ID array pointer to the initial (static) array). */ + pDbeWindowPriv->IDs = pDbeWindowPriv->initIDs; + + /* Initialize the buffer ID list. */ + pDbeWindowPriv->maxAvailableIDs = DBE_INIT_MAX_IDS; + pDbeWindowPriv->IDs[0] = stuff->buffer; + for (i = 1; i < DBE_INIT_MAX_IDS; i++) { + pDbeWindowPriv->IDs[i] = DBE_FREE_ID_ELEMENT; + } + + /* Actually connect the window priv to the window. */ + pWin->devPrivates[dbeWindowPrivIndex].ptr = (pointer) pDbeWindowPriv; + + } /* if -- There is no buffer associated with the window. */ + + else { + /* A buffer is already associated with the window. + * Add the new buffer ID to the array, reallocating the array memory + * if necessary. + */ + + /* Determine if there is a free element in the ID array. */ + for (i = 0; i < pDbeWindowPriv->maxAvailableIDs; i++) { + if (pDbeWindowPriv->IDs[i] == DBE_FREE_ID_ELEMENT) { + /* There is still room in the ID array. */ + break; + } + } + + if (i == pDbeWindowPriv->maxAvailableIDs) { + /* No more room in the ID array -- reallocate another array. */ + XID *pIDs; + + /* Setup an array pointer for the realloc operation below. */ + if (pDbeWindowPriv->maxAvailableIDs == DBE_INIT_MAX_IDS) { + /* We will malloc a new array. */ + pIDs = NULL; + } + else { + /* We will realloc a new array. */ + pIDs = pDbeWindowPriv->IDs; + } + + /* malloc/realloc a new array and initialize all elements to 0. */ + pDbeWindowPriv->IDs = (XID *) realloc(pIDs, + (pDbeWindowPriv-> + maxAvailableIDs + + DBE_INCR_MAX_IDS) * + sizeof(XID)); + if (!pDbeWindowPriv->IDs) { + return BadAlloc; + } + memset(&pDbeWindowPriv->IDs[pDbeWindowPriv->nBufferIDs], 0, + (pDbeWindowPriv->maxAvailableIDs + DBE_INCR_MAX_IDS - + pDbeWindowPriv->nBufferIDs) * sizeof(XID)); + + if (pDbeWindowPriv->maxAvailableIDs == DBE_INIT_MAX_IDS) { + /* We just went from using the initial (static) array to a + * newly allocated array. Copy the IDs from the initial array + * to the new array. + */ + memcpy(pDbeWindowPriv->IDs, pDbeWindowPriv->initIDs, + DBE_INIT_MAX_IDS * sizeof(XID)); + } + + pDbeWindowPriv->maxAvailableIDs += DBE_INCR_MAX_IDS; + } + + /* Finally, record the buffer ID in the array. */ + pDbeWindowPriv->IDs[i] = stuff->buffer; + + /* Associate the new ID with an existing window priv. */ + if (!AddResource(stuff->buffer, dbeWindowPrivResType, + (pointer) pDbeWindowPriv)) { + pDbeWindowPriv->IDs[i] = DBE_FREE_ID_ELEMENT; + return (BadAlloc); + } + + } /* else -- A buffer is already associated with the window. */ + + /* Call the DDX routine to allocate the back buffer. */ + status = (*pDbeScreenPriv->AllocBackBufferName) (pWin, stuff->buffer, + stuff->swapAction); + + if ((status != Success) && (pDbeWindowPriv->nBufferIDs == 0)) { + /* The DDX buffer allocation routine failed for the first buffer of + * this window. + */ + free(pDbeWindowPriv); + return (status); + } + + /* Increment the number of buffers (XIDs) associated with this window. */ + pDbeWindowPriv->nBufferIDs++; + + /* Set swap action on all calls. */ + pDbeWindowPriv->swapAction = stuff->swapAction; + + return (status); + +} /* ProcDbeAllocateBackBufferName() */ + +/****************************************************************************** + * + * DBE DIX Procedure: ProcDbeDeallocateBackBufferName + * + * Description: + * + * This function is for processing a DbeDeallocateBackBufferName request. + * This request frees a drawable ID that was obtained by a + * DbeAllocateBackBufferName request. + * + * Return Values: + * + * BadBuffer - buffer to deallocate is not associated with a window + * Success + * + *****************************************************************************/ + +static int +ProcDbeDeallocateBackBufferName(ClientPtr client) +{ + REQUEST(xDbeDeallocateBackBufferNameReq); + DbeWindowPrivPtr pDbeWindowPriv; + + int i; + + REQUEST_SIZE_MATCH(xDbeDeallocateBackBufferNameReq); + + /* Buffer name must be valid */ + if (!(pDbeWindowPriv = (DbeWindowPrivPtr) SecurityLookupIDByType(client, + stuff-> + buffer, + dbeWindowPrivResType, + SecurityDestroyAccess)) + || + !(SecurityLookupIDByType + (client, stuff->buffer, dbeDrawableResType, SecurityDestroyAccess))) { + client->errorValue = stuff->buffer; + return (dbeErrorBase + DbeBadBuffer); + } + + /* Make sure that the id is valid for the window. + * This is paranoid code since we already looked up the ID by type + * above. + */ + + for (i = 0; i < pDbeWindowPriv->nBufferIDs; i++) { + /* Loop through the ID list to find the ID. */ + if (pDbeWindowPriv->IDs[i] == stuff->buffer) { + break; + } + } + + if (i == pDbeWindowPriv->nBufferIDs) { + /* We did not find the ID in the ID list. */ + client->errorValue = stuff->buffer; + return dbeErrorBase + DbeBadBuffer; + } + + FreeResource(stuff->buffer, RT_NONE); + + return Success; + +} /* ProcDbeDeallocateBackBufferName() */ + +/****************************************************************************** + * + * DBE DIX Procedure: ProcDbeSwapBuffers + * + * Description: + * + * This function is for processing a DbeSwapBuffers request. + * This request swaps the buffers for all windows listed, applying the + * appropriate swap action for each window. + * + * Return Values: + * + * BadAlloc - local allocation failed; this return value is not defined + * by the protocol + * BadMatch - a window in request is not double-buffered; a window in + * request is listed more than once + * BadValue - invalid swap action is specified; no swap action is + * specified + * BadWindow - a window in request is not valid + * Success + * + *****************************************************************************/ + +static int +ProcDbeSwapBuffers(ClientPtr client) +{ + REQUEST(xDbeSwapBuffersReq); + WindowPtr pWin; + DbeScreenPrivPtr pDbeScreenPriv; + DbeSwapInfoPtr swapInfo; + xDbeSwapInfo *dbeSwapInfo; + int error; + int i, j; + int nStuff; + + REQUEST_AT_LEAST_SIZE(xDbeSwapBuffersReq); + nStuff = stuff->n; /* use local variable for performance. */ + + if (nStuff == 0) { + return Success; + } + + if (nStuff > UINT32_MAX / sizeof(DbeSwapInfoRec)) + return BadAlloc; + + /* Get to the swap info appended to the end of the request. */ + dbeSwapInfo = (xDbeSwapInfo *) &stuff[1]; + + /* Allocate array to record swap information. */ + swapInfo = malloc(nStuff * sizeof(DbeSwapInfoRec)); + if (swapInfo == NULL) { + return BadAlloc; + } + + for (i = 0; i < nStuff; i++) { + /* Check all windows to swap. */ + + /* Each window must be a valid window - BadWindow. */ + if (!(pWin = SecurityLookupWindow(dbeSwapInfo[i].window, client, + SecurityWriteAccess))) { + free(swapInfo); + return (BadWindow); + } + + /* Each window must be double-buffered - BadMatch. */ + if (DBE_WINDOW_PRIV(pWin) == NULL) { + free(swapInfo); + return BadMatch; + } + + /* Each window must only be specified once - BadMatch. */ + for (j = i + 1; j < nStuff; j++) { + if (dbeSwapInfo[i].window == dbeSwapInfo[j].window) { + free(swapInfo); + return BadMatch; + } + } + + /* Each swap action must be valid - BadValue. */ + if ((dbeSwapInfo[i].swapAction != XdbeUndefined) && + (dbeSwapInfo[i].swapAction != XdbeBackground) && + (dbeSwapInfo[i].swapAction != XdbeUntouched) && + (dbeSwapInfo[i].swapAction != XdbeCopied)) { + free(swapInfo); + return BadValue; + } + + /* Everything checks out OK. Fill in the swap info array. */ + swapInfo[i].pWindow = pWin; + swapInfo[i].swapAction = dbeSwapInfo[i].swapAction; + + } /* for (i = 0; i < nStuff; i++) */ + + /* Call the DDX routine to perform the swap(s). The DDX routine should + * scan the swap list (swap info), swap any buffers that it knows how to + * handle, delete them from the list, and update nStuff to indicate how + * many windows it did not handle. + * + * This scheme allows a range of sophistication in the DDX SwapBuffers() + * implementation. Naive implementations could just swap the first buffer + * in the list, move the last buffer to the front, decrement nStuff, and + * return. The next level of sophistication could be to scan the whole + * list for windows on the same screen. Up another level, the DDX routine + * could deal with cross-screen synchronization. + */ + + while (nStuff > 0) { + pDbeScreenPriv = DBE_SCREEN_PRIV_FROM_WINDOW(swapInfo[0].pWindow); + error = (*pDbeScreenPriv->SwapBuffers) (client, &nStuff, swapInfo); + if (error != Success) { + free(swapInfo); + return (error); + } + } + + free(swapInfo); + return (Success); + +} /* ProcDbeSwapBuffers() */ + +/****************************************************************************** + * + * DBE DIX Procedure: ProcDbeBeginIdiom + * + * Description: + * + * This function is for processing a DbeBeginIdiom request. + * This request informs the server that a complex swap will immediately + * follow this request. + * + * Return Values: + * + * Success + * + *****************************************************************************/ + +static int +ProcDbeBeginIdiom(ClientPtr client) +{ + /* REQUEST(xDbeBeginIdiomReq); */ + DbeScreenPrivPtr pDbeScreenPriv; + + int i; + + REQUEST_SIZE_MATCH(xDbeBeginIdiomReq); + + for (i = 0; i < screenInfo.numScreens; i++) { + pDbeScreenPriv = DBE_SCREEN_PRIV(screenInfo.screens[i]); + + /* Call the DDX begin idiom procedure if there is one. */ + if (pDbeScreenPriv->BeginIdiom) { + (*pDbeScreenPriv->BeginIdiom) (client); + } + } + + return (Success); + +} /* ProcDbeBeginIdiom() */ + +/****************************************************************************** + * + * DBE DIX Procedure: ProcDbeGetVisualInfo + * + * Description: + * + * This function is for processing a ProcDbeGetVisualInfo request. + * This request returns information about which visuals support + * double buffering. + * + * Return Values: + * + * BadDrawable - value in screen specifiers is not a valid drawable + * Success + * + *****************************************************************************/ + +static int +ProcDbeGetVisualInfo(ClientPtr client) +{ + REQUEST(xDbeGetVisualInfoReq); + DbeScreenPrivPtr pDbeScreenPriv; + xDbeGetVisualInfoReply rep; + Drawable *drawables; + DrawablePtr *pDrawables = NULL; + int i, j; + int count; /* number of visual infos in reply */ + int length; /* length of reply */ + ScreenPtr pScreen; + XdbeScreenVisualInfo *pScrVisInfo; + + REQUEST_AT_LEAST_SIZE(xDbeGetVisualInfoReq); + + if (stuff->n > UINT32_MAX / sizeof(DrawablePtr)) + return BadAlloc; + /* Make sure any specified drawables are valid. */ + if (stuff->n != 0) { + if (!(pDrawables = malloc(stuff->n * + sizeof(DrawablePtr)))) { + return (BadAlloc); + } + + drawables = (Drawable *) &stuff[1]; + + for (i = 0; i < stuff->n; i++) { + if (! + (pDrawables[i] = + (DrawablePtr) SecurityLookupDrawable(drawables[i], client, + SecurityReadAccess))) { + free(pDrawables); + return (BadDrawable); + } + } + } + + count = (stuff->n == 0) ? screenInfo.numScreens : stuff->n; + if (!(pScrVisInfo = malloc(count * + sizeof + (XdbeScreenVisualInfo)))) + { + if (pDrawables) { + free(pDrawables); + } + + return (BadAlloc); + } + + length = 0; + + for (i = 0; i < count; i++) { + pScreen = (stuff->n == 0) ? screenInfo.screens[i] : + pDrawables[i]->pScreen; + pDbeScreenPriv = DBE_SCREEN_PRIV(pScreen); + + if (!(*pDbeScreenPriv->GetVisualInfo) (pScreen, &pScrVisInfo[i])) { + /* We failed to alloc pScrVisInfo[i].visinfo. */ + + /* Free visinfos that we allocated for previous screen infos. */ + for (j = 0; j < i; j++) { + free(pScrVisInfo[j].visinfo); + } + + /* Free pDrawables if we needed to allocate it above. */ + if (pDrawables) { + free(pDrawables); + } + + return (BadAlloc); + } + + /* Account for n, number of xDbeVisInfo items in list. */ + length += sizeof(CARD32); + + /* Account for n xDbeVisInfo items */ + length += pScrVisInfo[i].count * sizeof(xDbeVisInfo); + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = length >> 2; + rep.m = count; + + if (client->swapped) { + swaps(&rep.sequenceNumber); + swapl(&rep.length); + swapl(&rep.m); + } + + /* Send off reply. */ + WriteToClient(client, sizeof(xDbeGetVisualInfoReply), (char *) &rep); + + for (i = 0; i < count; i++) { + CARD32 data32; + + /* For each screen in the reply, send off the visual info */ + + /* Send off number of visuals. */ + data32 = (CARD32) pScrVisInfo[i].count; + + if (client->swapped) { + swapl(&data32); + } + + WriteToClient(client, sizeof(CARD32), (char *) &data32); + + /* Now send off visual info items. */ + for (j = 0; j < pScrVisInfo[i].count; j++) { + xDbeVisInfo visInfo; + + /* Copy the data in the client data structure to a protocol + * data structure. We will send data to the client from the + * protocol data structure. + */ + + visInfo.visualID = (CARD32) pScrVisInfo[i].visinfo[j].visual; + visInfo.depth = (CARD8) pScrVisInfo[i].visinfo[j].depth; + visInfo.perfLevel = (CARD8) pScrVisInfo[i].visinfo[j].perflevel; + + if (client->swapped) { + swapl(&visInfo.visualID); + + /* We do not need to swap depth and perfLevel since they are + * already 1 byte quantities. + */ + } + + /* Write visualID(32), depth(8), perfLevel(8), and pad(16). */ + WriteToClient(client, 2 * sizeof(CARD32), + (char *) &visInfo.visualID); + } + } + + /* Clean up memory. */ + for (i = 0; i < count; i++) { + free(pScrVisInfo[i].visinfo); + } + free(pScrVisInfo); + + if (pDrawables) { + free(pDrawables); + } + + return (client->noClientException); + +} /* ProcDbeGetVisualInfo() */ + +/****************************************************************************** + * + * DBE DIX Procedure: ProcDbeGetbackBufferAttributes + * + * Description: + * + * This function is for processing a ProcDbeGetbackBufferAttributes + * request. This request returns information about a back buffer. + * + * Return Values: + * + * Success + * + *****************************************************************************/ + +static int +ProcDbeGetBackBufferAttributes(ClientPtr client) +{ + REQUEST(xDbeGetBackBufferAttributesReq); + xDbeGetBackBufferAttributesReply rep; + + DbeWindowPrivPtr pDbeWindowPriv; + + REQUEST_SIZE_MATCH(xDbeGetBackBufferAttributesReq); + + if (!(pDbeWindowPriv = (DbeWindowPrivPtr) SecurityLookupIDByType(client, + stuff-> + buffer, + dbeWindowPrivResType, + SecurityReadAccess))) + { + rep.attributes = None; + } + else { + rep.attributes = pDbeWindowPriv->pWindow->drawable.id; + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + + if (client->swapped) { + swaps(&rep.sequenceNumber); + swapl(&rep.length); + swapl(&rep.attributes); + } + + WriteToClient(client, sizeof(xDbeGetBackBufferAttributesReply), + (char *) &rep); + return (client->noClientException); + +} /* ProcDbeGetbackBufferAttributes() */ + +/****************************************************************************** + * + * DBE DIX Procedure: ProcDbeDispatch + * + * Description: + * + * This function dispatches DBE requests. + * + *****************************************************************************/ + +static int +ProcDbeDispatch(ClientPtr client) +{ + REQUEST(xReq); + + switch (stuff->data) { + case X_DbeGetVersion: + return (ProcDbeGetVersion(client)); + + case X_DbeAllocateBackBufferName: + return (ProcDbeAllocateBackBufferName(client)); + + case X_DbeDeallocateBackBufferName: + return (ProcDbeDeallocateBackBufferName(client)); + + case X_DbeSwapBuffers: + return (ProcDbeSwapBuffers(client)); + + case X_DbeBeginIdiom: + return Success; + + case X_DbeEndIdiom: + return Success; + + case X_DbeGetVisualInfo: + return (ProcDbeGetVisualInfo(client)); + + case X_DbeGetBackBufferAttributes: + return (ProcDbeGetBackBufferAttributes(client)); + + default: + return BadRequest; + } + +} /* ProcDbeDispatch() */ + +/****************************************************************************** + * + * DBE DIX Procedure: SProcDbeGetVersion + * + * Description: + * + * This function is for processing a DbeGetVersion request on a swapped + * server. This request returns the major and minor version numbers of + * this extension. + * + * Return Values: + * + * Success + * + *****************************************************************************/ + +static int +SProcDbeGetVersion(ClientPtr client) +{ + REQUEST(xDbeGetVersionReq); + + swaps(&stuff->length); + return (ProcDbeGetVersion(client)); + +} /* SProcDbeGetVersion() */ + +/****************************************************************************** + * + * DBE DIX Procedure: SProcDbeAllocateBackBufferName + * + * Description: + * + * This function is for processing a DbeAllocateBackBufferName request on + * a swapped server. This request allocates a drawable ID used to refer + * to the back buffer of a window. + * + * Return Values: + * + * BadAlloc - server can not allocate resources + * BadIDChoice - id is out of range for client; id is already in use + * BadMatch - window is not an InputOutput window; + * visual of window is not on list returned by + * DBEGetVisualInfo; + * BadValue - invalid swap action is specified + * BadWindow - window is not a valid window + * Success + * + *****************************************************************************/ + +static int +SProcDbeAllocateBackBufferName(ClientPtr client) +{ + REQUEST(xDbeAllocateBackBufferNameReq); + + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xDbeAllocateBackBufferNameReq); + + swapl(&stuff->window); + swapl(&stuff->buffer); + /* stuff->swapAction is a byte. We do not need to swap this field. */ + + return (ProcDbeAllocateBackBufferName(client)); + +} /* SProcDbeAllocateBackBufferName() */ + +/****************************************************************************** + * + * DBE DIX Procedure: SProcDbeDeallocateBackBufferName + * + * Description: + * + * This function is for processing a DbeDeallocateBackBufferName request + * on a swapped server. This request frees a drawable ID that was + * obtained by a DbeAllocateBackBufferName request. + * + * Return Values: + * + * BadBuffer - buffer to deallocate is not associated with a window + * Success + * + *****************************************************************************/ + +static int +SProcDbeDeallocateBackBufferName(ClientPtr client) +{ + REQUEST(xDbeDeallocateBackBufferNameReq); + + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xDbeDeallocateBackBufferNameReq); + + swapl(&stuff->buffer); + + return (ProcDbeDeallocateBackBufferName(client)); + +} /* SProcDbeDeallocateBackBufferName() */ + +/****************************************************************************** + * + * DBE DIX Procedure: SProcDbeSwapBuffers + * + * Description: + * + * This function is for processing a DbeSwapBuffers request on a swapped + * server. This request swaps the buffers for all windows listed, + * applying the appropriate swap action for each window. + * + * Return Values: + * + * BadMatch - a window in request is not double-buffered; a window in + * request is listed more than once; all windows in request do + * not have the same root + * BadValue - invalid swap action is specified + * BadWindow - a window in request is not valid + * Success + * + *****************************************************************************/ + +static int +SProcDbeSwapBuffers(ClientPtr client) +{ + REQUEST(xDbeSwapBuffersReq); + int i; + + xDbeSwapInfo *pSwapInfo; + + swaps(&stuff->length); + REQUEST_AT_LEAST_SIZE(xDbeSwapBuffersReq); + + swapl(&stuff->n); + + if (stuff->n != 0) { + pSwapInfo = (xDbeSwapInfo *) stuff + 1; + + /* The swap info following the fix part of this request is a window(32) + * followed by a 1 byte swap action and then 3 pad bytes. We only need + * to swap the window information. + */ + for (i = 0; i < stuff->n; i++) { + swapl(&pSwapInfo->window); + } + } + + return (ProcDbeSwapBuffers(client)); + +} /* SProcDbeSwapBuffers() */ + +/****************************************************************************** + * + * DBE DIX Procedure: SProcDbeBeginIdiom + * + * Description: + * + * This function is for processing a DbeBeginIdiom request on a swapped + * server. This request informs the server that a complex swap will + * immediately follow this request. + * + * Return Values: + * + * Success + * + *****************************************************************************/ + +static int +SProcDbeBeginIdiom(ClientPtr client) +{ + REQUEST(xDbeBeginIdiomReq); + + swaps(&stuff->length); + return (ProcDbeBeginIdiom(client)); + +} /* SProcDbeBeginIdiom() */ + +/****************************************************************************** + * + * DBE DIX Procedure: SProcDbeGetVisualInfo + * + * Description: + * + * This function is for processing a ProcDbeGetVisualInfo request on a + * swapped server. This request returns information about which visuals + * support double buffering. + * + * Return Values: + * + * BadDrawable - value in screen specifiers is not a valid drawable + * Success + * + *****************************************************************************/ + +static int +SProcDbeGetVisualInfo(ClientPtr client) +{ + REQUEST(xDbeGetVisualInfoReq); + + swaps(&stuff->length); + REQUEST_AT_LEAST_SIZE(xDbeGetVisualInfoReq); + + swapl(&stuff->n); + SwapRestL(stuff); + + return (ProcDbeGetVisualInfo(client)); + +} /* SProcDbeGetVisualInfo() */ + +/****************************************************************************** + * + * DBE DIX Procedure: SProcDbeGetbackBufferAttributes + * + * Description: + * + * This function is for processing a ProcDbeGetbackBufferAttributes + * request on a swapped server. This request returns information about a + * back buffer. + * + * Return Values: + * + * Success + * + *****************************************************************************/ + +static int +SProcDbeGetBackBufferAttributes(ClientPtr client) +{ + REQUEST(xDbeGetBackBufferAttributesReq); + + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xDbeGetBackBufferAttributesReq); + + swapl(&stuff->buffer); + + return (ProcDbeGetBackBufferAttributes(client)); + +} /* SProcDbeGetBackBufferAttributes() */ + +/****************************************************************************** + * + * DBE DIX Procedure: SProcDbeDispatch + * + * Description: + * + * This function dispatches DBE requests on a swapped server. + * + *****************************************************************************/ + +static int +SProcDbeDispatch(ClientPtr client) +{ + REQUEST(xReq); + + switch (stuff->data) { + case X_DbeGetVersion: + return (SProcDbeGetVersion(client)); + + case X_DbeAllocateBackBufferName: + return (SProcDbeAllocateBackBufferName(client)); + + case X_DbeDeallocateBackBufferName: + return (SProcDbeDeallocateBackBufferName(client)); + + case X_DbeSwapBuffers: + return (SProcDbeSwapBuffers(client)); + + case X_DbeBeginIdiom: + return (SProcDbeBeginIdiom(client)); + + case X_DbeEndIdiom: + return (Success); + + case X_DbeGetVisualInfo: + return (SProcDbeGetVisualInfo(client)); + + case X_DbeGetBackBufferAttributes: + return (SProcDbeGetBackBufferAttributes(client)); + + default: + return (BadRequest); + } + +} /* SProcDbeDispatch() */ + +/****************************************************************************** + * + * DBE DIX Procedure: DbeSetupBackgroundPainter + * + * Description: + * + * This function sets up pGC to clear pixmaps. + * + * Return Values: + * + * TRUE - setup was successful + * FALSE - the window's background state is NONE + * + *****************************************************************************/ + +static Bool +DbeSetupBackgroundPainter(WindowPtr pWin, GCPtr pGC) +{ + pointer gcvalues[4]; + + int ts_x_origin, ts_y_origin; + + PixUnion background; + + int backgroundState; + + Mask gcmask; + + /* First take care of any ParentRelative stuff by altering the + * tile/stipple origin to match the coordinates of the upper-left + * corner of the first ancestor without a ParentRelative background. + * This coordinate is, of course, negative. + */ + ts_x_origin = ts_y_origin = 0; + while (pWin->backgroundState == ParentRelative) { + ts_x_origin -= pWin->origin.x; + ts_y_origin -= pWin->origin.y; + + pWin = pWin->parent; + } + backgroundState = pWin->backgroundState; + background = pWin->background; + + switch (backgroundState) { + case BackgroundPixel: + gcvalues[0] = (pointer) background.pixel; + gcvalues[1] = (pointer) FillSolid; + gcmask = GCForeground | GCFillStyle; + break; + + case BackgroundPixmap: + gcvalues[0] = (pointer) FillTiled; + gcvalues[1] = (pointer) background.pixmap; + gcvalues[2] = (pointer) (long) ts_x_origin; + gcvalues[3] = (pointer) (long) ts_y_origin; + gcmask = GCFillStyle | GCTile | GCTileStipXOrigin | GCTileStipYOrigin; + break; + + default: + /* pWin->backgroundState == None */ + return (FALSE); + } + + if (DoChangeGC(pGC, gcmask, (XID *) gcvalues, TRUE) != 0) { + return (FALSE); + } + + return (TRUE); + +} /* DbeSetupBackgroundPainter() */ + +/****************************************************************************** + * + * DBE DIX Procedure: DbeDrawableDelete + * + * Description: + * + * This is the resource delete function for dbeDrawableResType. + * It is registered when the drawable resource type is created in + * DbeExtensionInit(). + * + * To make resource deletion simple, we do not do anything in this function + * and leave all resource deleteion to DbeWindowPrivDelete(), which will + * eventually be called or already has been called. Deletion functions are + * not guaranteed to be called in any particular order. + * + *****************************************************************************/ +static int +DbeDrawableDelete(pointer pDrawable, XID id) +{ + return Success; + +} /* DbeDrawableDelete() */ + +/****************************************************************************** + * + * DBE DIX Procedure: DbeWindowPrivDelete + * + * Description: + * + * This is the resource delete function for dbeWindowPrivResType. + * It is registered when the drawable resource type is created in + * DbeExtensionInit(). + * + *****************************************************************************/ +static int +DbeWindowPrivDelete(pointer pDbeWinPriv, XID id) +{ + DbeScreenPrivPtr pDbeScreenPriv; + DbeWindowPrivPtr pDbeWindowPriv = (DbeWindowPrivPtr) pDbeWinPriv; + int i; + + /* + ************************************************************************** + ** Remove the buffer ID from the ID array. + ************************************************************************** + */ + + /* Find the ID in the ID array. */ + i = 0; + while ((i < pDbeWindowPriv->nBufferIDs) && (pDbeWindowPriv->IDs[i] != id)) { + i++; + } + + if (i == pDbeWindowPriv->nBufferIDs) { + /* We did not find the ID in the array. We should never get here. */ + return BadValue; + } + + /* Remove the ID from the array. */ + + if (i < (pDbeWindowPriv->nBufferIDs - 1)) { + /* Compress the buffer ID array, overwriting the ID in the process. */ + memmove(&pDbeWindowPriv->IDs[i], &pDbeWindowPriv->IDs[i + 1], + (pDbeWindowPriv->nBufferIDs - i - 1) * sizeof(XID)); + } + else { + /* We are removing the last ID in the array, in which case, the + * assignement below is all that we need to do. + */ + } + pDbeWindowPriv->IDs[pDbeWindowPriv->nBufferIDs - 1] = DBE_FREE_ID_ELEMENT; + + pDbeWindowPriv->nBufferIDs--; + + /* If an extended array was allocated, then check to see if the remaining + * buffer IDs will fit in the static array. + */ + + if ((pDbeWindowPriv->maxAvailableIDs > DBE_INIT_MAX_IDS) && + (pDbeWindowPriv->nBufferIDs == DBE_INIT_MAX_IDS)) { + /* Copy the IDs back into the static array. */ + memcpy(pDbeWindowPriv->initIDs, pDbeWindowPriv->IDs, + DBE_INIT_MAX_IDS * sizeof(XID)); + + /* Free the extended array; use the static array. */ + free(pDbeWindowPriv->IDs); + pDbeWindowPriv->IDs = pDbeWindowPriv->initIDs; + pDbeWindowPriv->maxAvailableIDs = DBE_INIT_MAX_IDS; + } + + /* + ************************************************************************** + ** Perform DDX level tasks. + ************************************************************************** + */ + + pDbeScreenPriv = DBE_SCREEN_PRIV_FROM_WINDOW_PRIV((DbeWindowPrivPtr) + pDbeWindowPriv); + (*pDbeScreenPriv->WinPrivDelete) ((DbeWindowPrivPtr) pDbeWindowPriv, id); + + /* + ************************************************************************** + ** Perform miscellaneous tasks if this is the last buffer associated + ** with the window. + ************************************************************************** + */ + + if (pDbeWindowPriv->nBufferIDs == 0) { + /* Reset the DBE window priv pointer. */ + pDbeWindowPriv->pWindow->devPrivates[dbeWindowPrivIndex].ptr = + (pointer) NULL; + + /* We are done with the window priv. */ + free(pDbeWindowPriv); + } + + return (Success); + +} /* DbeWindowPrivDelete() */ + +/****************************************************************************** + * + * DBE DIX Procedure: DbeResetProc + * + * Description: + * + * This routine is called at the end of every server generation. + * It deallocates any memory reserved for the extension and performs any + * other tasks related to shutting down the extension. + * + *****************************************************************************/ +static void +DbeResetProc(ExtensionEntry * extEntry) +{ + int i; + + ScreenPtr pScreen; + + DbeScreenPrivPtr pDbeScreenPriv; + + if (dbeScreenPrivIndex < 0) { + return; + } + + for (i = 0; i < screenInfo.numScreens; i++) { + pScreen = screenInfo.screens[i]; + pDbeScreenPriv = DBE_SCREEN_PRIV(pScreen); + + if (pDbeScreenPriv) { + /* Unwrap DestroyWindow, which was wrapped in DbeExtensionInit(). */ + pScreen->DestroyWindow = pDbeScreenPriv->DestroyWindow; + + if (pDbeScreenPriv->ResetProc) + (*pDbeScreenPriv->ResetProc) (pScreen); + + if (pDbeScreenPriv->winPrivPrivSizes) { + free(pDbeScreenPriv->winPrivPrivSizes); + } + + free(pDbeScreenPriv); + } + } + + /* We want to init the initialization function table after every server + * reset in DbeRegisterFunction(). + */ + firstRegistrationPass = TRUE; + +} /* DbeResetProc() */ + +/****************************************************************************** + * + * DBE DIX Procedure: DbeDestroyWindow + * + * Description: + * + * This is the wrapper for pScreen->DestroyWindow. + * This function frees buffer resources for a window before it is + * destroyed. + * + *****************************************************************************/ + +static Bool +DbeDestroyWindow(WindowPtr pWin) +{ + DbeScreenPrivPtr pDbeScreenPriv; + DbeWindowPrivPtr pDbeWindowPriv; + ScreenPtr pScreen; + Bool ret; + + /* + ************************************************************************** + ** 1. Unwrap the member routine. + ************************************************************************** + */ + + pScreen = pWin->drawable.pScreen; + pDbeScreenPriv = DBE_SCREEN_PRIV(pScreen); + pScreen->DestroyWindow = pDbeScreenPriv->DestroyWindow; + + /* + ************************************************************************** + ** 2. Do any work necessary before the member routine is called. + ** + ** Call the window priv delete function for all buffer IDs associated + ** with this window. + ************************************************************************** + */ + + if ((pDbeWindowPriv = DBE_WINDOW_PRIV(pWin))) { + while (pDbeWindowPriv) { + /* *DbeWinPrivDelete() will free the window private and set it to + * NULL if there are no more buffer IDs associated with this + * window. + */ + FreeResource(pDbeWindowPriv->IDs[0], RT_NONE); + pDbeWindowPriv = DBE_WINDOW_PRIV(pWin); + } + } + + /* + ************************************************************************** + ** 3. Call the member routine, saving its result if necessary. + ************************************************************************** + */ + + ret = (*pScreen->DestroyWindow) (pWin); + + /* + ************************************************************************** + ** 4. Rewrap the member routine, restoring the wrapper value first in case + ** the wrapper (or something that it wrapped) change this value. + ************************************************************************** + */ + + pDbeScreenPriv->DestroyWindow = pScreen->DestroyWindow; + pScreen->DestroyWindow = DbeDestroyWindow; + + /* + ************************************************************************** + ** 5. Do any work necessary after the member routine has been called. + ** + ** In this case we do not need to do anything. + ************************************************************************** + */ + + return ret; + +} /* DbeDestroyWindow() */ + +/****************************************************************************** + * + * DBE DIX Procedure: DbeExtensionInit + * + * Description: + * + * Called from InitExtensions in main() + * + *****************************************************************************/ + +void +DbeExtensionInit(void) +{ + ExtensionEntry *extEntry; + + int i, j; + + ScreenPtr pScreen = NULL; + + DbeScreenPrivPtr pDbeScreenPriv; + + int nStubbedScreens = 0; + + Bool ddxInitSuccess; + + + /* Allocate private pointers in windows and screens. */ + + if ((dbeScreenPrivIndex = AllocateScreenPrivateIndex()) < 0) { + return; + } + + if ((dbeWindowPrivIndex = AllocateWindowPrivateIndex()) < 0) { + return; + } + + /* Initialize the priv priv counts between server generations. */ + winPrivPrivCount = 0; + + /* Create the resource types. */ + dbeDrawableResType = + CreateNewResourceType(DbeDrawableDelete) | RC_CACHED | RC_DRAWABLE; + dbeWindowPrivResType = CreateNewResourceType(DbeWindowPrivDelete); + + for (i = 0; i < screenInfo.numScreens; i++) { + /* For each screen, set up DBE screen privates and init DIX and DDX + * interface. + */ + + pScreen = screenInfo.screens[i]; + + if (!AllocateWindowPrivate(pScreen, dbeWindowPrivIndex, 0) || + !(pDbeScreenPriv = + calloc(sizeof(DbeScreenPrivRec), 1))) { + /* If we can not alloc a window or screen private, + * then free any privates that we already alloc'ed and return + */ + + for (j = 0; j < i; j++) { + free(screenInfo.screens[j]->devPrivates[dbeScreenPrivIndex]. + ptr); + screenInfo.screens[j]->devPrivates[dbeScreenPrivIndex].ptr = + NULL; + } + return; + } + + pScreen->devPrivates[dbeScreenPrivIndex].ptr = (pointer) pDbeScreenPriv; + + /* Store the DBE priv priv size info for later use when allocating + * priv privs at the driver level. + */ + pDbeScreenPriv->winPrivPrivLen = 0; + pDbeScreenPriv->winPrivPrivSizes = (unsigned *) NULL; + pDbeScreenPriv->totalWinPrivSize = sizeof(DbeWindowPrivRec); + + /* Copy the resource types */ + pDbeScreenPriv->dbeDrawableResType = dbeDrawableResType; + pDbeScreenPriv->dbeWindowPrivResType = dbeWindowPrivResType; + + /* Copy the private indices */ + pDbeScreenPriv->dbeScreenPrivIndex = dbeScreenPrivIndex; + pDbeScreenPriv->dbeWindowPrivIndex = dbeWindowPrivIndex; + + if (DbeInitFunct[i]) { + /* This screen supports DBE. */ + + /* Setup DIX. */ + pDbeScreenPriv->SetupBackgroundPainter = DbeSetupBackgroundPainter; + pDbeScreenPriv->AllocWinPriv = DbeAllocWinPriv; + pDbeScreenPriv->AllocWinPrivPrivIndex = DbeAllocWinPrivPrivIndex; + pDbeScreenPriv->AllocWinPrivPriv = DbeAllocWinPrivPriv; + + /* Setup DDX. */ + ddxInitSuccess = (*DbeInitFunct[i]) (pScreen, pDbeScreenPriv); + + /* DDX DBE initialization may have the side affect of + * reallocating pDbeScreenPriv, so we need to update it. + */ + pDbeScreenPriv = DBE_SCREEN_PRIV(pScreen); + + if (ddxInitSuccess) { + /* Wrap DestroyWindow. The DDX initialization function + * already wrapped PositionWindow for us. + */ + + pDbeScreenPriv->DestroyWindow = pScreen->DestroyWindow; + pScreen->DestroyWindow = DbeDestroyWindow; + } + else { + /* DDX initialization failed. Stub the screen. */ + DbeStubScreen(pDbeScreenPriv, &nStubbedScreens); + } + } + else { + /* This screen does not support DBE. */ + +#ifndef DISABLE_MI_DBE_BY_DEFAULT + /* Setup DIX. */ + pDbeScreenPriv->SetupBackgroundPainter = DbeSetupBackgroundPainter; + pDbeScreenPriv->AllocWinPriv = DbeAllocWinPriv; + pDbeScreenPriv->AllocWinPrivPrivIndex = DbeAllocWinPrivPrivIndex; + pDbeScreenPriv->AllocWinPrivPriv = DbeAllocWinPrivPriv; + + /* Setup DDX. */ + ddxInitSuccess = miDbeInit(pScreen, pDbeScreenPriv); + + /* DDX DBE initialization may have the side affect of + * reallocating pDbeScreenPriv, so we need to update it. + */ + pDbeScreenPriv = DBE_SCREEN_PRIV(pScreen); + + if (ddxInitSuccess) { + /* Wrap DestroyWindow. The DDX initialization function + * already wrapped PositionWindow for us. + */ + + pDbeScreenPriv->DestroyWindow = pScreen->DestroyWindow; + pScreen->DestroyWindow = DbeDestroyWindow; + } + else { + /* DDX initialization failed. Stub the screen. */ + DbeStubScreen(pDbeScreenPriv, &nStubbedScreens); + } +#else + DbeStubScreen(pDbeScreenPriv, &nStubbedScreens); +#endif + + } + + } /* for (i = 0; i < screenInfo.numScreens; i++) */ + + if (nStubbedScreens == screenInfo.numScreens) { + /* All screens stubbed. Clean up and return. */ + + for (i = 0; i < screenInfo.numScreens; i++) { + free(screenInfo.screens[i]->devPrivates[dbeScreenPrivIndex].ptr); + pScreen->devPrivates[dbeScreenPrivIndex].ptr = NULL; + } + return; + } + + /* Now add the extension. */ + extEntry = AddExtension(DBE_PROTOCOL_NAME, DbeNumberEvents, + DbeNumberErrors, ProcDbeDispatch, SProcDbeDispatch, + DbeResetProc, StandardMinorOpcode); + + dbeErrorBase = extEntry->errorBase; + +} /* DbeExtensionInit() */ diff --git a/dbe/dbestruct.h b/dbe/dbestruct.h new file mode 100644 index 0000000..c102a6f --- /dev/null +++ b/dbe/dbestruct.h @@ -0,0 +1,226 @@ +/****************************************************************************** + * + * Copyright (c) 1994, 1995 Hewlett-Packard Company + * + * 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, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * 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 HEWLETT-PACKARD COMPANY 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 Hewlett-Packard + * Company 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 Hewlett-Packard Company. + * + * Header file for DIX-related DBE + * + *****************************************************************************/ + +#ifndef DBE_STRUCT_H +#define DBE_STRUCT_H + +/* INCLUDES */ + +#define NEED_DBE_PROTOCOL +#include +#include "windowstr.h" + +typedef struct { + VisualID visual; /* one visual ID that supports double-buffering */ + int depth; /* depth of visual in bits */ + int perflevel; /* performance level of visual */ +} XdbeVisualInfo; + +typedef struct { + int count; /* number of items in visual_depth */ + XdbeVisualInfo *visinfo; /* list of visuals & depths for scrn */ +} XdbeScreenVisualInfo; + +/* DEFINES */ + +#define DBE_SCREEN_PRIV(pScreen) \ + ((dbeScreenPrivIndex < 0) ? \ + NULL : \ + ((DbeScreenPrivPtr)((pScreen)->devPrivates[dbeScreenPrivIndex].ptr))) + +#define DBE_SCREEN_PRIV_FROM_DRAWABLE(pDrawable) \ + DBE_SCREEN_PRIV((pDrawable)->pScreen) + +#define DBE_SCREEN_PRIV_FROM_WINDOW_PRIV(pDbeWindowPriv) \ + DBE_SCREEN_PRIV((pDbeWindowPriv)->pWindow->drawable.pScreen) + +#define DBE_SCREEN_PRIV_FROM_WINDOW(pWindow) \ + DBE_SCREEN_PRIV((pWindow)->drawable.pScreen) + +#define DBE_SCREEN_PRIV_FROM_PIXMAP(pPixmap) \ + DBE_SCREEN_PRIV((pPixmap)->drawable.pScreen) + +#define DBE_SCREEN_PRIV_FROM_GC(pGC)\ + DBE_SCREEN_PRIV((pGC)->pScreen) + +#define DBE_WINDOW_PRIV(pWindow)\ + ((dbeWindowPrivIndex < 0) ? \ + NULL : \ + ((DbeWindowPrivPtr)(pWindow->devPrivates[dbeWindowPrivIndex].ptr))) + +/* Initial size of the buffer ID array in the window priv. */ +#define DBE_INIT_MAX_IDS 2 + +/* Reallocation increment for the buffer ID array. */ +#define DBE_INCR_MAX_IDS 4 + +/* Marker for free elements in the buffer ID array. */ +#define DBE_FREE_ID_ELEMENT 0 + +/* TYPEDEFS */ + +/* Record used to pass swap information between DIX and DDX swapping + * procedures. + */ +typedef struct _DbeSwapInfoRec { + WindowPtr pWindow; + unsigned char swapAction; + +} DbeSwapInfoRec, *DbeSwapInfoPtr; + +/* + ****************************************************************************** + ** Per-window data + ****************************************************************************** + */ + +typedef struct _DbeWindowPrivRec { + /* A pointer to the window with which the DBE window private (buffer) is + * associated. + */ + WindowPtr pWindow; + + /* Last known swap action for this buffer. Legal values for this field + * are XdbeUndefined, XdbeBackground, XdbeUntouched, and XdbeCopied. + */ + unsigned char swapAction; + + /* Last known buffer size. + */ + unsigned short width, height; + + /* Coordinates used for static gravity when the window is positioned. + */ + short x, y; + + /* Number of XIDs associated with this buffer. + */ + int nBufferIDs; + + /* Capacity of the current buffer ID array, IDs. */ + int maxAvailableIDs; + + /* Pointer to the array of buffer IDs. This initially points to initIDs. + * When the static limit of the initIDs array is reached, the array is + * reallocated and this pointer is set to the new array instead of initIDs. + */ + XID *IDs; + + /* Initial array of buffer IDs. We are defining the XID array within the + * window priv to optimize for data locality. In most cases, only one + * buffer will be associated with a window. Having the array declared + * here can prevent us from accessing the data in another memory page, + * possibly resulting in a page swap and loss of performance. Initially we + * will use this array to store buffer IDs. For situations where we have + * more IDs than can fit in this static array, we will allocate a larger + * array to use, possibly suffering a performance loss. + */ + XID initIDs[DBE_INIT_MAX_IDS]; + + /* Device-specific private information. + */ + DevUnion *devPrivates; + +} DbeWindowPrivRec, *DbeWindowPrivPtr; + +/* + ****************************************************************************** + ** Per-screen data + ****************************************************************************** + */ + +typedef struct _DbeScreenPrivRec { + /* Info for creating window privs */ + int winPrivPrivLen; /* Length of privs in DbeWindowPrivRec */ + unsigned int *winPrivPrivSizes; /* Array of private record sizes */ + unsigned int totalWinPrivSize; /* PrivRec + size of all priv priv ptrs */ + + /* Resources created by DIX to be used by DDX */ + RESTYPE dbeDrawableResType; + RESTYPE dbeWindowPrivResType; + + /* Private indices created by DIX to be used by DDX */ + int dbeScreenPrivIndex; + int dbeWindowPrivIndex; + + /* Wrapped functions + * It is the responsibilty of the DDX layer to wrap PositionWindow(). + * DbeExtensionInit wraps DestroyWindow(). + */ + PositionWindowProcPtr PositionWindow; + DestroyWindowProcPtr DestroyWindow; + + /* Per-screen DIX routines */ + Bool (*SetupBackgroundPainter) (WindowPtr /*pWin */ , + GCPtr /*pGC */ + ); + DbeWindowPrivPtr(*AllocWinPriv) (ScreenPtr /*pScreen */ + ); + int (*AllocWinPrivPrivIndex) (void); + Bool (*AllocWinPrivPriv) (ScreenPtr /*pScreen */ , + int /*index */ , + unsigned /*amount */ + ); + + /* Per-screen DDX routines */ + Bool (*GetVisualInfo) (ScreenPtr /*pScreen */ , + XdbeScreenVisualInfo * /*pVisInfo */ + ); + int (*AllocBackBufferName) (WindowPtr /*pWin */ , + XID /*bufId */ , + int /*swapAction */ + ); + int (*SwapBuffers) (ClientPtr /*client */ , + int * /*pNumWindows */ , + DbeSwapInfoPtr /*swapInfo */ + ); + void (*BeginIdiom) (ClientPtr /*client */ + ); + void (*EndIdiom) (ClientPtr /*client */ + ); + void (*WinPrivDelete) (DbeWindowPrivPtr /*pDbeWindowPriv */ , + XID /*bufId */ + ); + void (*ResetProc) (ScreenPtr /*pScreen */ + ); + void (*ValidateBuffer) (WindowPtr /*pWin */ , + XID /*bufId */ , + Bool /*dstbuffer */ + ); + + /* Device-specific private information. + */ + DevUnion *devPrivates; + +} DbeScreenPrivRec, *DbeScreenPrivPtr; + +#endif /* DBE_STRUCT_H */ diff --git a/dbe/midbe.c b/dbe/midbe.c new file mode 100644 index 0000000..a513149 --- /dev/null +++ b/dbe/midbe.c @@ -0,0 +1,791 @@ +/****************************************************************************** + * + * Copyright (c) 1994, 1995 Hewlett-Packard Company + * + * 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, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * 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 HEWLETT-PACKARD COMPANY 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 Hewlett-Packard + * Company 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 Hewlett-Packard Company. + * + * Machine-independent DBE code + * + *****************************************************************************/ + +/* INCLUDES */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#include +#include "misc.h" +#include "os.h" +#include "windowstr.h" +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "extnsionst.h" +#include "dixstruct.h" +#include "resource.h" +#include "opaque.h" +#include "dbestruct.h" +#include "midbestr.h" +#include "regionstr.h" +#include "gcstruct.h" +#include "inputstr.h" +#include "midbe.h" + +#include + +/* DEFINES */ + +/* TYPEDEFS */ + +/* GLOBALS */ + +static int miDbePrivPrivGeneration = 0; + +static int miDbeWindowPrivPrivIndex = -1; + +RESTYPE dbeDrawableResType; + +RESTYPE dbeWindowPrivResType; + +int dbeScreenPrivIndex = -1; + +int dbeWindowPrivIndex = -1; + +/****************************************************************************** + * + * DBE MI Procedure: miDbeGetVisualInfo + * + * Description: + * + * This is the MI function for the DbeGetVisualInfo request. This function + * is called through pDbeScreenPriv->GetVisualInfo. This function is also + * called for the DbeAllocateBackBufferName request at the extension level; + * it is called by ProcDbeAllocateBackBufferName() in dbe.c. + * + * If memory allocation fails or we can not get the visual info, this + * function returns FALSE. Otherwise, it returns TRUE for success. + * + *****************************************************************************/ + +static Bool +miDbeGetVisualInfo(ScreenPtr pScreen, XdbeScreenVisualInfo * pScrVisInfo) +{ + int i, j, k; + int count; + DepthPtr pDepth; + XdbeVisualInfo *visInfo; + + /* Determine number of visuals for this screen. */ + for (i = 0, count = 0; i < pScreen->numDepths; i++) { + count += pScreen->allowedDepths[i].numVids; + } + + if (!count) + return FALSE; + + /* Allocate an array of XdbeVisualInfo items. */ + if (!(visInfo = malloc(count * sizeof(XdbeVisualInfo)))) { + return FALSE; /* memory alloc failure */ + } + + for (i = 0, k = 0; i < pScreen->numDepths; i++) { + /* For each depth of this screen, get visual information. */ + + pDepth = &pScreen->allowedDepths[i]; + + for (j = 0; j < pDepth->numVids; j++) { + /* For each visual for this depth of this screen, get visual ID + * and visual depth. Since this is MI code, we will always return + * the same performance level for all visuals (0). A higher + * performance level value indicates higher performance. + */ + visInfo[k].visual = pDepth->vids[j]; + visInfo[k].depth = pDepth->depth; + visInfo[k].perflevel = 0; + k++; + } + } + + /* Record the number of visuals and point visual_depth to + * the array of visual info. + */ + pScrVisInfo->count = count; + pScrVisInfo->visinfo = visInfo; + + return TRUE; /* success */ + +} /* miDbeGetVisualInfo() */ + +/****************************************************************************** + * + * DBE MI Procedure: miAllocBackBufferName + * + * Description: + * + * This is the MI function for the DbeAllocateBackBufferName request. + * + *****************************************************************************/ + +static int +miDbeAllocBackBufferName(WindowPtr pWin, XID bufId, int swapAction) +{ + ScreenPtr pScreen; + + DbeWindowPrivPtr pDbeWindowPriv; + + MiDbeWindowPrivPrivPtr pDbeWindowPrivPriv; + + DbeScreenPrivPtr pDbeScreenPriv; + + GCPtr pGC; + + xRectangle clearRect; + + pScreen = pWin->drawable.pScreen; + pDbeWindowPriv = DBE_WINDOW_PRIV(pWin); + + if (pDbeWindowPriv->nBufferIDs == 0) { + /* There is no buffer associated with the window. + * We have to create the window priv priv. Remember, the window + * priv was created at the DIX level, so all we need to do is + * create the priv priv and attach it to the priv. + */ + + pDbeScreenPriv = DBE_SCREEN_PRIV(pScreen); + + /* Setup the window priv priv. */ + pDbeWindowPrivPriv = MI_DBE_WINDOW_PRIV_PRIV(pDbeWindowPriv); + pDbeWindowPrivPriv->pDbeWindowPriv = pDbeWindowPriv; + + /* Get a front pixmap. */ + if (!(pDbeWindowPrivPriv->pFrontBuffer = + (*pScreen->CreatePixmap) (pScreen, pDbeWindowPriv->width, + pDbeWindowPriv->height, + pWin->drawable.depth))) { + return (BadAlloc); + } + + /* Get a back pixmap. */ + if (!(pDbeWindowPrivPriv->pBackBuffer = + (*pScreen->CreatePixmap) (pScreen, pDbeWindowPriv->width, + pDbeWindowPriv->height, + pWin->drawable.depth))) { + (*pScreen->DestroyPixmap) (pDbeWindowPrivPriv->pFrontBuffer); + return (BadAlloc); + } + + /* Make the back pixmap a DBE drawable resource. */ + if (!AddResource(bufId, dbeDrawableResType, + (pointer) pDbeWindowPrivPriv->pBackBuffer)) { + /* free the buffer and the drawable resource */ + FreeResource(bufId, RT_NONE); + return (BadAlloc); + } + + /* Attach the priv priv to the priv. */ + pDbeWindowPriv->devPrivates[miDbeWindowPrivPrivIndex].ptr = + (pointer) pDbeWindowPrivPriv; + + /* Clear the back buffer. */ + pGC = GetScratchGC(pWin->drawable.depth, pWin->drawable.pScreen); + if ((*pDbeScreenPriv->SetupBackgroundPainter) (pWin, pGC)) { + ValidateGC((DrawablePtr) pDbeWindowPrivPriv->pBackBuffer, pGC); + clearRect.x = clearRect.y = 0; + clearRect.width = pDbeWindowPrivPriv->pBackBuffer->drawable.width; + clearRect.height = pDbeWindowPrivPriv->pBackBuffer->drawable.height; + (*pGC->ops->PolyFillRect) ((DrawablePtr) pDbeWindowPrivPriv-> + pBackBuffer, pGC, 1, &clearRect); + } + FreeScratchGC(pGC); + + } /* if no buffer associated with the window */ + + else { + /* A buffer is already associated with the window. + * Place the new buffer ID information at the head of the ID list. + */ + + /* Associate the new ID with an existing pixmap. */ + pDbeWindowPrivPriv = MI_DBE_WINDOW_PRIV_PRIV(pDbeWindowPriv); + if (!AddResource(bufId, dbeDrawableResType, + (pointer) pDbeWindowPrivPriv->pBackBuffer)) { + return (BadAlloc); + } + + } + + return (Success); + +} /* miDbeAllocBackBufferName() */ + +/****************************************************************************** + * + * DBE MI Procedure: miDbeAliasBuffers + * + * Description: + * + * This function associates all XIDs of a buffer with the back pixmap + * stored in the window priv. + * + *****************************************************************************/ + +static void +miDbeAliasBuffers(DbeWindowPrivPtr pDbeWindowPriv) +{ + int i; + + MiDbeWindowPrivPrivPtr pDbeWindowPrivPriv = + MI_DBE_WINDOW_PRIV_PRIV(pDbeWindowPriv); + + for (i = 0; i < pDbeWindowPriv->nBufferIDs; i++) { + ChangeResourceValue(pDbeWindowPriv->IDs[i], dbeDrawableResType, + (pointer) pDbeWindowPrivPriv->pBackBuffer); + } + +} /* miDbeAliasBuffers() */ + +/****************************************************************************** + * + * DBE MI Procedure: miDbeSwapBuffers + * + * Description: + * + * This is the MI function for the DbeSwapBuffers request. + * + *****************************************************************************/ + +static int +miDbeSwapBuffers(ClientPtr client, int *pNumWindows, DbeSwapInfoPtr swapInfo) +{ + DbeScreenPrivPtr pDbeScreenPriv; + + GCPtr pGC; + + WindowPtr pWin; + + MiDbeWindowPrivPrivPtr pDbeWindowPrivPriv; + + PixmapPtr pTmpBuffer; + + xRectangle clearRect; + + pWin = swapInfo[0].pWindow; + pDbeScreenPriv = DBE_SCREEN_PRIV_FROM_WINDOW(pWin); + pDbeWindowPrivPriv = MI_DBE_WINDOW_PRIV_PRIV_FROM_WINDOW(pWin); + pGC = GetScratchGC(pWin->drawable.depth, pWin->drawable.pScreen); + + /* + ********************************************************************** + ** Setup before swap. + ********************************************************************** + */ + + switch (swapInfo[0].swapAction) { + case XdbeUndefined: + break; + + case XdbeBackground: + break; + + case XdbeUntouched: + ValidateGC((DrawablePtr) pDbeWindowPrivPriv->pFrontBuffer, pGC); + (*pGC->ops->CopyArea) ((DrawablePtr) pWin, + (DrawablePtr) pDbeWindowPrivPriv->pFrontBuffer, + pGC, 0, 0, pWin->drawable.width, + pWin->drawable.height, 0, 0); + break; + + case XdbeCopied: + break; + + } + + /* + ********************************************************************** + ** Swap. + ********************************************************************** + */ + + ValidateGC((DrawablePtr) pWin, pGC); + (*pGC->ops->CopyArea) ((DrawablePtr) pDbeWindowPrivPriv->pBackBuffer, + (DrawablePtr) pWin, pGC, 0, 0, + pWin->drawable.width, pWin->drawable.height, 0, 0); + + /* + ********************************************************************** + ** Tasks after swap. + ********************************************************************** + */ + + switch (swapInfo[0].swapAction) { + case XdbeUndefined: + break; + + case XdbeBackground: + if ((*pDbeScreenPriv->SetupBackgroundPainter) (pWin, pGC)) { + ValidateGC((DrawablePtr) pDbeWindowPrivPriv->pBackBuffer, pGC); + clearRect.x = 0; + clearRect.y = 0; + clearRect.width = pDbeWindowPrivPriv->pBackBuffer->drawable.width; + clearRect.height = pDbeWindowPrivPriv->pBackBuffer->drawable.height; + (*pGC->ops->PolyFillRect) ((DrawablePtr) pDbeWindowPrivPriv-> + pBackBuffer, pGC, 1, &clearRect); + } + break; + + case XdbeUntouched: + /* Swap pixmap pointers. */ + pTmpBuffer = pDbeWindowPrivPriv->pBackBuffer; + pDbeWindowPrivPriv->pBackBuffer = pDbeWindowPrivPriv->pFrontBuffer; + pDbeWindowPrivPriv->pFrontBuffer = pTmpBuffer; + + miDbeAliasBuffers(pDbeWindowPrivPriv->pDbeWindowPriv); + + break; + + case XdbeCopied: + break; + + } + + /* Remove the swapped window from the swap information array and decrement + * pNumWindows to indicate to the DIX level how many windows were actually + * swapped. + */ + + if (*pNumWindows > 1) { + /* We were told to swap more than one window, but we only swapped the + * first one. Remove the first window in the list by moving the last + * window to the beginning. + */ + swapInfo[0].pWindow = swapInfo[*pNumWindows - 1].pWindow; + swapInfo[0].swapAction = swapInfo[*pNumWindows - 1].swapAction; + + /* Clear the last window information just to be safe. */ + swapInfo[*pNumWindows - 1].pWindow = (WindowPtr) NULL; + swapInfo[*pNumWindows - 1].swapAction = 0; + } + else { + /* Clear the window information just to be safe. */ + swapInfo[0].pWindow = (WindowPtr) NULL; + swapInfo[0].swapAction = 0; + } + + (*pNumWindows)--; + + FreeScratchGC(pGC); + + return Success; + +} /* miSwapBuffers() */ + +/****************************************************************************** + * + * DBE MI Procedure: miDbeWinPrivDelete + * + * Description: + * + * This is the MI function for deleting the dbeWindowPrivResType resource. + * This function is invoked indirectly by calling FreeResource() to free + * the resources associated with a DBE buffer ID. There are 5 ways that + * miDbeWinPrivDelete() can be called by FreeResource(). They are: + * + * - A DBE window is destroyed, in which case the DbeDestroyWindow() + * wrapper is invoked. The wrapper calls FreeResource() for all DBE + * buffer IDs. + * + * - miDbeAllocBackBufferName() calls FreeResource() to clean up resources + * after a buffer allocation failure. + * + * - The PositionWindow wrapper, miDbePositionWindow(), calls + * FreeResource() when it fails to create buffers of the new size. + * FreeResource() is called for all DBE buffer IDs. + * + * - FreeClientResources() calls FreeResource() when a client dies or the + * the server resets. + * + * When FreeResource() is called for a DBE buffer ID, the delete function + * for the only other type of DBE resource, dbeDrawableResType, is also + * invoked. This delete function (DbeDrawableDelete) is a NOOP to make + * resource deletion easier. It is not guaranteed which delete function is + * called first. Hence, we will let miDbeWinPrivDelete() free all DBE + * resources. + * + * This function deletes/frees the following stuff associated with + * the window private: + * + * - the ID node in the ID list representing the passed in ID. + * + * In addition, pDbeWindowPriv->nBufferIDs is decremented. + * + * If this function is called for the last/only buffer ID for a window, + * these are additionally deleted/freed: + * + * - the front and back pixmaps + * - the window priv itself + * + *****************************************************************************/ + +static void +miDbeWinPrivDelete(DbeWindowPrivPtr pDbeWindowPriv, XID bufId) +{ + MiDbeWindowPrivPrivPtr pDbeWindowPrivPriv; + + if (pDbeWindowPriv->nBufferIDs != 0) { + /* We still have at least one more buffer ID associated with this + * window. + */ + return; + } + + /* We have no more buffer IDs associated with this window. We need to + * free some stuff. + */ + + pDbeWindowPrivPriv = MI_DBE_WINDOW_PRIV_PRIV(pDbeWindowPriv); + + /* Destroy the front and back pixmaps. */ + if (pDbeWindowPrivPriv->pFrontBuffer) { + (*pDbeWindowPriv->pWindow->drawable.pScreen-> + DestroyPixmap) (pDbeWindowPrivPriv->pFrontBuffer); + } + if (pDbeWindowPrivPriv->pBackBuffer) { + (*pDbeWindowPriv->pWindow->drawable.pScreen-> + DestroyPixmap) (pDbeWindowPrivPriv->pBackBuffer); + } + +} /* miDbeWinPrivDelete() */ + +/****************************************************************************** + * + * DBE MI Procedure: miDbePositionWindow + * + * Description: + * + * This function was cloned from miMbxPositionWindow() in mimultibuf.c. + * This function resizes the buffer when the window is resized. + * + *****************************************************************************/ + +static Bool +miDbePositionWindow(WindowPtr pWin, int x, int y) +{ + ScreenPtr pScreen; + DbeScreenPrivPtr pDbeScreenPriv; + DbeWindowPrivPtr pDbeWindowPriv; + int width, height; + int dx, dy, dw, dh; + int sourcex, sourcey; + int destx, desty; + int savewidth, saveheight; + PixmapPtr pFrontBuffer; + PixmapPtr pBackBuffer; + Bool clear; + GCPtr pGC; + xRectangle clearRect; + Bool ret; + + /* + ************************************************************************** + ** 1. Unwrap the member routine. + ************************************************************************** + */ + + pScreen = pWin->drawable.pScreen; + pDbeScreenPriv = DBE_SCREEN_PRIV(pScreen); + pScreen->PositionWindow = pDbeScreenPriv->PositionWindow; + + /* + ************************************************************************** + ** 2. Do any work necessary before the member routine is called. + ** + ** In this case we do not need to do anything. + ************************************************************************** + */ + + /* + ************************************************************************** + ** 3. Call the member routine, saving its result if necessary. + ************************************************************************** + */ + + ret = (*pScreen->PositionWindow) (pWin, x, y); + + /* + ************************************************************************** + ** 4. Rewrap the member routine, restoring the wrapper value first in case + ** the wrapper (or something that it wrapped) change this value. + ************************************************************************** + */ + + pDbeScreenPriv->PositionWindow = pScreen->PositionWindow; + pScreen->PositionWindow = miDbePositionWindow; + + /* + ************************************************************************** + ** 5. Do any work necessary after the member routine has been called. + ************************************************************************** + */ + + if (!(pDbeWindowPriv = DBE_WINDOW_PRIV(pWin))) { + return ret; + } + + if (pDbeWindowPriv->width == pWin->drawable.width && + pDbeWindowPriv->height == pWin->drawable.height) { + return ret; + } + + width = pWin->drawable.width; + height = pWin->drawable.height; + + dx = pWin->drawable.x - pDbeWindowPriv->x; + dy = pWin->drawable.y - pDbeWindowPriv->y; + dw = width - pDbeWindowPriv->width; + dh = height - pDbeWindowPriv->height; + + GravityTranslate(0, 0, -dx, -dy, dw, dh, pWin->bitGravity, &destx, &desty); + + clear = ((pDbeWindowPriv->width < (unsigned short) width) || + (pDbeWindowPriv->height < (unsigned short) height) || + (pWin->bitGravity == ForgetGravity)); + + sourcex = 0; + sourcey = 0; + savewidth = pDbeWindowPriv->width; + saveheight = pDbeWindowPriv->height; + + /* Clip rectangle to source and destination. */ + if (destx < 0) { + savewidth += destx; + sourcex -= destx; + destx = 0; + } + + if (destx + savewidth > width) { + savewidth = width - destx; + } + + if (desty < 0) { + saveheight += desty; + sourcey -= desty; + desty = 0; + } + + if (desty + saveheight > height) { + saveheight = height - desty; + } + + pDbeWindowPriv->width = width; + pDbeWindowPriv->height = height; + pDbeWindowPriv->x = pWin->drawable.x; + pDbeWindowPriv->y = pWin->drawable.y; + + pGC = GetScratchGC(pWin->drawable.depth, pScreen); + + if (clear) { + if ((*pDbeScreenPriv->SetupBackgroundPainter) (pWin, pGC)) { + clearRect.x = 0; + clearRect.y = 0; + clearRect.width = width; + clearRect.height = height; + } + else { + clear = FALSE; + } + } + + /* Create DBE buffer pixmaps equal to size of resized window. */ + pFrontBuffer = (*pScreen->CreatePixmap) (pScreen, width, height, + pWin->drawable.depth); + + pBackBuffer = (*pScreen->CreatePixmap) (pScreen, width, height, + pWin->drawable.depth); + + if (!pFrontBuffer || !pBackBuffer) { + /* We failed at creating 1 or 2 of the pixmaps. */ + + if (pFrontBuffer) { + (*pScreen->DestroyPixmap) (pFrontBuffer); + } + + if (pBackBuffer) { + (*pScreen->DestroyPixmap) (pBackBuffer); + } + + /* Destroy all buffers for this window. */ + while (pDbeWindowPriv) { + /* DbeWindowPrivDelete() will free the window private if there no + * more buffer IDs associated with this window. + */ + FreeResource(pDbeWindowPriv->IDs[0], RT_NONE); + pDbeWindowPriv = DBE_WINDOW_PRIV(pWin); + } + + FreeScratchGC(pGC); + return (FALSE); + } + + else { + /* Clear out the new DBE buffer pixmaps. */ + + MiDbeWindowPrivPrivPtr pDbeWindowPrivPriv; + + pDbeWindowPrivPriv = MI_DBE_WINDOW_PRIV_PRIV(pDbeWindowPriv); + ValidateGC((DrawablePtr) pFrontBuffer, pGC); + + /* I suppose this could avoid quite a bit of work if + * it computed the minimal area required. + */ + if (clear) { + (*pGC->ops->PolyFillRect) ((DrawablePtr) pFrontBuffer, pGC, 1, + &clearRect); + (*pGC->ops->PolyFillRect) ((DrawablePtr) pBackBuffer, pGC, 1, + &clearRect); + } + + /* Copy the contents of the old DBE pixmaps to the new pixmaps. */ + if (pWin->bitGravity != ForgetGravity) { + (*pGC->ops->CopyArea) ((DrawablePtr) pDbeWindowPrivPriv-> + pFrontBuffer, (DrawablePtr) pFrontBuffer, + pGC, sourcex, sourcey, savewidth, saveheight, + destx, desty); + (*pGC->ops->CopyArea) ((DrawablePtr) pDbeWindowPrivPriv-> + pBackBuffer, (DrawablePtr) pBackBuffer, pGC, + sourcex, sourcey, savewidth, saveheight, + destx, desty); + } + + /* Destroy the old pixmaps, and point the DBE window priv to the new + * pixmaps. + */ + + (*pScreen->DestroyPixmap) (pDbeWindowPrivPriv->pFrontBuffer); + (*pScreen->DestroyPixmap) (pDbeWindowPrivPriv->pBackBuffer); + + pDbeWindowPrivPriv->pFrontBuffer = pFrontBuffer; + pDbeWindowPrivPriv->pBackBuffer = pBackBuffer; + + /* Make sure all XID are associated with the new back pixmap. */ + miDbeAliasBuffers(pDbeWindowPriv); + + FreeScratchGC(pGC); + } + + return (ret); + +} /* miDbePositionWindow() */ + +/****************************************************************************** + * + * DBE MI Procedure: miDbeResetProc + * + * Description: + * + * This function is called from DbeResetProc(), which is called at the end + * of every server generation. This function peforms any MI-specific + * shutdown tasks. + * + *****************************************************************************/ + +static void +miDbeResetProc(ScreenPtr pScreen) +{ + DbeScreenPrivPtr pDbeScreenPriv; + + pDbeScreenPriv = DBE_SCREEN_PRIV(pScreen); + + /* Unwrap wrappers */ + pScreen->PositionWindow = pDbeScreenPriv->PositionWindow; + +} /* miDbeResetProc() */ + +static void +miDbeNopValidateBuffer(WindowPtr pWin, XID bufId, Bool dstbuffer) +{ +} + +/****************************************************************************** + * + * DBE MI Procedure: miDbeInit + * + * Description: + * + * This is the MI initialization function called by DbeExtensionInit(). + * + *****************************************************************************/ + +Bool +miDbeInit(ScreenPtr pScreen, DbeScreenPrivPtr pDbeScreenPriv) +{ + /* Copy resource types created by DIX */ + dbeDrawableResType = pDbeScreenPriv->dbeDrawableResType; + dbeWindowPrivResType = pDbeScreenPriv->dbeWindowPrivResType; + + /* Copy private indices created by DIX */ + dbeScreenPrivIndex = pDbeScreenPriv->dbeScreenPrivIndex; + dbeWindowPrivIndex = pDbeScreenPriv->dbeWindowPrivIndex; + + /* Reset the window priv privs if generations do not match. */ + if (miDbePrivPrivGeneration != serverGeneration) { + /* + ********************************************************************** + ** Allocate the window priv priv. + ********************************************************************** + */ + + miDbeWindowPrivPrivIndex = (*pDbeScreenPriv->AllocWinPrivPrivIndex) (); + + /* Make sure we only do this code once. */ + miDbePrivPrivGeneration = serverGeneration; + + } /* if -- Reset priv privs. */ + + if (!(*pDbeScreenPriv->AllocWinPrivPriv) (pScreen, + miDbeWindowPrivPrivIndex, + sizeof(MiDbeWindowPrivPrivRec))) { + return (FALSE); + } + + /* Wrap functions. */ + pDbeScreenPriv->PositionWindow = pScreen->PositionWindow; + pScreen->PositionWindow = miDbePositionWindow; + + /* Initialize the per-screen DBE function pointers. */ + pDbeScreenPriv->GetVisualInfo = miDbeGetVisualInfo; + pDbeScreenPriv->AllocBackBufferName = miDbeAllocBackBufferName; + pDbeScreenPriv->SwapBuffers = miDbeSwapBuffers; + pDbeScreenPriv->BeginIdiom = 0; + pDbeScreenPriv->EndIdiom = 0; + pDbeScreenPriv->ResetProc = miDbeResetProc; + pDbeScreenPriv->WinPrivDelete = miDbeWinPrivDelete; + + /* The mi implementation doesn't need buffer validation. */ + pDbeScreenPriv->ValidateBuffer = miDbeNopValidateBuffer; + + return (TRUE); + +} /* miDbeInit() */ diff --git a/dbe/midbe.h b/dbe/midbe.h new file mode 100644 index 0000000..051528f --- /dev/null +++ b/dbe/midbe.h @@ -0,0 +1,43 @@ +/****************************************************************************** + * Copyright (c) 1994, 1995 Hewlett-Packard Company + * + * 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, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * 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 HEWLETT-PACKARD COMPANY 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 Hewlett-Packard + * Company 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 Hewlett-Packard Company. + * + * Header file for users of machine-independent DBE code + * + *****************************************************************************/ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#ifndef MIDBE_H +#define MIDBE_H + +/* EXTERNS */ + +extern Bool miDbeInit(ScreenPtr pScreen, DbeScreenPrivPtr pDbeScreenPriv); + +#endif /* MIDBE_H */ diff --git a/dbe/midbestr.h b/dbe/midbestr.h new file mode 100644 index 0000000..2447444 --- /dev/null +++ b/dbe/midbestr.h @@ -0,0 +1,93 @@ +/****************************************************************************** + * + * Copyright (c) 1994, 1995 Hewlett-Packard Company + * + * 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, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * 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 HEWLETT-PACKARD COMPANY 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 Hewlett-Packard + * Company 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 Hewlett-Packard Company. + * + * Header file for users of machine-independent DBE code + * + *****************************************************************************/ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#ifndef MIDBE_STRUCT_H +#define MIDBE_STRUCT_H + +/* DEFINES */ + +#define MI_DBE_WINDOW_PRIV_PRIV(pDbeWindowPriv) \ + (((miDbeWindowPrivPrivIndex < 0) || (!pDbeWindowPriv)) ? \ + NULL : \ + ((MiDbeWindowPrivPrivPtr) \ + ((pDbeWindowPriv)->devPrivates[miDbeWindowPrivPrivIndex].ptr))) + +#define MI_DBE_WINDOW_PRIV_PRIV_FROM_WINDOW(pWin)\ + MI_DBE_WINDOW_PRIV_PRIV(DBE_WINDOW_PRIV(pWin)) + +#define MI_DBE_SCREEN_PRIV_PRIV(pDbeScreenPriv) \ + (((miDbeScreenPrivPrivIndex < 0) || (!pDbeScreenPriv)) ? \ + NULL : \ + ((MiDbeScreenPrivPrivPtr) \ + ((pDbeScreenPriv)->devPrivates[miDbeScreenPrivPrivIndex].ptr))) + +/* TYPEDEFS */ + +typedef struct _MiDbeWindowPrivPrivRec { + /* Place machine-specific fields in here. + * Since this is mi code, we do not really have machine-specific fields. + */ + + /* Pointer to a drawable that contains the contents of the back buffer. + */ + PixmapPtr pBackBuffer; + + /* Pointer to a drawable that contains the contents of the front buffer. + * This pointer is only used for the XdbeUntouched swap action. For that + * swap action, we need to copy the front buffer (window) contents into + * this drawable, copy the contents of current back buffer drawable (the + * back buffer) into the window, swap the front and back drawable pointers, + * and then swap the drawable/resource associations in the resource + * database. + */ + PixmapPtr pFrontBuffer; + + /* Pointer back to our window private with which we are associated. */ + DbeWindowPrivPtr pDbeWindowPriv; + +} MiDbeWindowPrivPrivRec, *MiDbeWindowPrivPrivPtr; + +typedef struct _MiDbeScreenPrivPrivRec { + /* Place machine-specific fields in here. + * Since this is mi code, we do not really have machine-specific fields. + */ + + /* Pointer back to our screen private with which we are associated. */ + DbeScreenPrivPtr pDbeScreenPriv; + +} MiDbeScreenPrivPrivRec, *MiDbeScreenPrivPrivPtr; + +#endif /* MIDBE_STRUCT_H */ diff --git a/dix/Makefile.am b/dix/Makefile.am new file mode 100644 index 0000000..9f64c95 --- /dev/null +++ b/dix/Makefile.am @@ -0,0 +1,33 @@ +noinst_LTLIBRARIES = libdix.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 diff --git a/dix/atom.c b/dix/atom.c new file mode 100644 index 0000000..bd44ea8 --- /dev/null +++ b/dix/atom.c @@ -0,0 +1,212 @@ +/*********************************************************** + +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 +#endif + +#include +#include +#include +#include +#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) +{ + NodePtr *np; + + unsigned i; + + int comp; + + 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) { + NodePtr nd; + + nd = malloc(sizeof(NodeRec)); + if (!nd) + return BAD_RESOURCE; + if (lastAtom < XA_LAST_PREDEFINED) { + nd->string = string; + } + else { + nd->string = malloc(len + 1); + if (!nd->string) { + free(nd); + return BAD_RESOURCE; + } + strncpy(nd->string, string, (int) len); + nd->string[len] = 0; + } + if ((lastAtom + 1) >= tableLength) { + NodePtr *table; + + table = (NodePtr *) realloc(nodeTable, + tableLength * (2 * sizeof(NodePtr))); + if (!table) { + if (nd->string != string) + free(nd->string); + free(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) + free(patom->string); + free(patom); +} + +void +FreeAllAtoms() +{ + if (atomRoot == (NodePtr) NULL) + return; + FreeAtom(atomRoot); + atomRoot = (NodePtr) NULL; + free(nodeTable); + nodeTable = (NodePtr *) NULL; + lastAtom = None; +} + +void +InitAtoms() +{ + FreeAllAtoms(); + tableLength = InitialTableSize; + nodeTable = malloc(InitialTableSize * sizeof(NodePtr)); + if (!nodeTable) + AtomError(); + nodeTable[None] = (NodePtr) NULL; + MakePredeclaredAtoms(); + if (lastAtom != XA_LAST_PREDEFINED) + AtomError(); +} diff --git a/dix/colormap.c b/dix/colormap.c new file mode 100644 index 0000000..83b4ad1 --- /dev/null +++ b/dix/colormap.c @@ -0,0 +1,2555 @@ +/*********************************************************** + +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 +#endif + +#include +#include +#include +#include +#include +#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) +#define ALPHAMASK(vis) 0 + +#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; + + EntryPtr pent; + + int i; + + 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 = malloc(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 = malloc(size * sizeof(Pixel)); + if (!ppix) { + free(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 = malloc(size * sizeof(Pixel)); + if (!ppix) { + free(pmap->clientPixelsRed[client]); + free(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 = malloc(size * sizeof(Pixel)); + if (!ppix) { + free(pmap->clientPixelsGreen[client]); + free(pmap->clientPixelsRed[client]); + free(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 = + calloc(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; + + 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++) + free(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) + free(pent->co.shco.red); + if (--pent->co.shco.green->refcnt == 0) + free(pent->co.shco.green); + if (--pent->co.shco.blue->refcnt == 0) + free(pent->co.shco.blue); + } + } + } + if ((pmap->class | DynamicClass) == DirectColor) { + for (i = 0; i < MAXCLIENTS; i++) { + free(pmap->clientPixelsGreen[i]); + free(pmap->clientPixelsBlue[i]); + } + } + + if (pmap->devPrivates) + free(pmap->devPrivates); + + free(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; + 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; + + 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; + + 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) + free(pent->co.shco.red); + if (--pent->co.shco.green->refcnt == 0) + free(pent->co.shco.green); + if (--pent->co.shco.blue->refcnt == 0) + free(pent->co.shco.blue); + pent->fShared = FALSE; + } + pent->refcnt = 0; + *pCount += 1; + } +} + +static void +UpdateColors(ColormapPtr pmap) +{ + xColorItem *defs; + + xColorItem *pdef; + + EntryPtr pent; + + 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 *) realloc(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 *) realloc(pmap->clientPixelsRed[client], + (npix + 1) * sizeof(Pixel)); + if (!ppix) + return (BadAlloc); + ppix[npix] = pixR; + pmap->clientPixelsRed[client] = ppix; + npix = pmap->numPixelsGreen[client]; + ppix = (Pixel *) realloc(pmap->clientPixelsGreen[client], + (npix + 1) * sizeof(Pixel)); + if (!ppix) + return (BadAlloc); + ppix[npix] = pixG; + pmap->clientPixelsGreen[client] = ppix; + npix = pmap->numPixelsBlue[client]; + ppix = (Pixel *) realloc(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 = malloc(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; + + 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) +{ + 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 *) realloc(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) +{ + Pixel *ppix, *ppixStart; + + int class, n; + + class = pmap->class; + ppixStart = pmap->clientPixelsRed[client]; + if (class & DynamicClass) { + n = pmap->numPixelsRed[client]; + for (ppix = ppixStart; --n >= 0;) { + FreeCell(pmap, *ppix, REDMAP); + ppix++; + } + } + + free(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); + free(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); + free(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); + free(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 = malloc(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) + free(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; + + Pixel shift; + + 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 = malloc(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) + free(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 *) realloc(pmap->clientPixelsRed[client], + (pmap->numPixelsRed[client] + (c << r)) * + sizeof(Pixel)); + if (rpix) + pmap->clientPixelsRed[client] = rpix; + gpix = (Pixel *) realloc(pmap->clientPixelsGreen[client], + (pmap->numPixelsGreen[client] + (c << g)) * + sizeof(Pixel)); + if (gpix) + pmap->clientPixelsGreen[client] = gpix; + bpix = (Pixel *) realloc(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 *) realloc(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<>> + + */ + + 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] = malloc(sizeof(SHAREDCOLOR)))) { + for (z++; z < npixShared; z++) + free(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 *) realloc(ppixClient, npixNew * sizeof(Pixel)); + if (pptr) + ppixClient = pptr; + npixClient = npixNew; + } + else { + npixClient = 0; + free(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) +{ + Pixel pix; + + xColorItem *pdef; + + EntryPtr pent, pentT, pentLast; + + 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/dix/cursor.c b/dix/cursor.c new file mode 100644 index 0000000..a132e99 --- /dev/null +++ b/dix/cursor.c @@ -0,0 +1,442 @@ +/*********************************************************** + +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 +#endif + +#include +#include +#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; + +static CARD32 cursorSerial; + +static void +FreeCursorBits(CursorBitsPtr bits) +{ + if (--bits->refcnt > 0) + return; + free(bits->source); + free(bits->mask); +#ifdef ARGB_CURSOR + free(bits->argb); +#endif + if (bits->refcnt == 0) { + GlyphSharePtr *prev, this; + + for (prev = &sharedGlyphs; + (this = *prev) && (this->bits != bits); prev = &this->next); + if (this) { + *prev = this->next; + CloseFont(this->font, (Font) 0); + free(this); + } + free(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); + free(pCurs); + return (Success); +} + +/* + * We check for empty cursors so that we won't have to display them + */ +static void +CheckForEmptyMask(CursorBitsPtr bits) +{ + 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 = malloc(sizeof(CursorRec) + sizeof(CursorBits)); + if (!pCurs) { + free(psrcbits); + free(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; + pCurs->serialNumber = ++cursorSerial; + pCurs->name = None; + + 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); + free(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 = NULL; + + 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 = malloc(sizeof(CursorRec)); + if (!pCurs) + return BadAlloc; + bits = pShare->bits; + bits->refcnt++; + } + else { + if (!CursorMetricsFromGlyph(sourcefont, sourceChar, &cm)) { + client->errorValue = sourceChar; + return BadValue; + } + if (!maskfont) { + long n; + + unsigned char *mskptr; + + n = BitmapBytePad(cm.width) * (long) cm.height; + mskptr = mskbits = malloc(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) { + free(mskbits); + return res; + } + if (sourcefont != maskfont) { + pCurs = malloc(sizeof(CursorRec) + sizeof(CursorBits)); + if (pCurs) + bits = (CursorBitsPtr) ((char *) pCurs + sizeof(CursorRec)); + else + bits = (CursorBitsPtr) NULL; + } + else { + pCurs = malloc(sizeof(CursorRec)); + if (pCurs) + bits = malloc(sizeof(CursorBits)); + else + bits = (CursorBitsPtr) NULL; + } + if (!bits) { + free(pCurs); + free(mskbits); + free(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 = malloc(sizeof(GlyphShare)); + if (!pShare) { + FreeCursorBits(bits); + free(pCurs); + 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; + pCurs->serialNumber = ++cursorSerial; + pCurs->name = None; + + 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); + free(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/dix/devices.c b/dix/devices.c new file mode 100644 index 0000000..ca62f49 --- /dev/null +++ b/dix/devices.c @@ -0,0 +1,1363 @@ +/************************************************************ + +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 +#endif + +#include +#include "misc.h" +#include "resource.h" +#include +#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 + +#include "dispatch.h" +#include "swaprep.h" +#include "dixevents.h" + +DeviceIntPtr +AddInputDevice(DeviceProc deviceProc, Bool autoStart) +{ + DeviceIntPtr dev; + + if (inputInfo.numDevices >= MAX_DEVICES) + return (DeviceIntPtr) NULL; + dev = malloc(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; + dev->nPrivates = 0; + dev->devPrivates = NULL; + dev->unwrapProc = NULL; + inputInfo.off_devices = dev; + return dev; +} + +Bool +EnableDevice(register DeviceIntPtr dev) +{ + 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) +{ + 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() +{ + 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); + free(dev->name); + if (dev->key) { + free(dev->key->curKeySyms.map); + free(dev->key->modifierKeyMap); + free(dev->key); + } + free(dev->valuator); + free(dev->button); + if (dev->focus) { + free(dev->focus->trace); + free(dev->focus); + } + free(dev->proximity); + for (k = dev->kbdfeed; k; k = knext) { + knext = k->next; + free(k); + } + for (p = dev->ptrfeed; p; p = pnext) { + pnext = p->next; + free(p); + } + for (i = dev->intfeed; i; i = inext) { + inext = i->next; + free(i); + } + for (s = dev->stringfeed; s; s = snext) { + snext = s->next; + free(s->ctrl.symbols_supported); + free(s->ctrl.symbols_displayed); + free(s); + } + for (b = dev->bell; b; b = bnext) { + bnext = b->next; + free(b); + } + for (l = dev->leds; l; l = lnext) { + lnext = l->next; + free(l); + } + free(dev->sync.event); + free(dev); +} + +void +CloseDownDevices() +{ + 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) +{ + 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; + + device->public.processInputProc = ProcessPointerEvent; + device->public.realInputProc = ProcessPointerEvent; + device->ActivateGrab = ActivatePointerGrab; + device->DeactivateGrab = DeactivatePointerGrab; + if (!device->name) { + char *p = "pointer"; + + device->name = malloc(strlen(p) + 1); + strcpy(device->name, p); + } +} + +void +RegisterKeyboardDevice(DeviceIntPtr device) +{ + inputInfo.keyboard = device; + device->public.processInputProc = ProcessKeyboardEvent; + device->public.realInputProc = ProcessKeyboardEvent; + device->ActivateGrab = ActivateKeyboardGrab; + device->DeactivateGrab = DeactivateKeyboardGrab; + if (!device->name) { + char *k = "keyboard"; + + device->name = malloc(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 = malloc(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)); + free(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 = malloc(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; + + KeyClassPtr keyc; + + keyc = malloc(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)) { + free(keyc->curKeySyms.map); + free(keyc->modifierKeyMap); + free(keyc); + return FALSE; + } + dev->key = keyc; + return TRUE; +} + +_X_EXPORT Bool +InitButtonClassDeviceStruct(register DeviceIntPtr dev, int numButtons, + CARD8 *map) +{ + ButtonClassPtr butc; + + int i; + + butc = malloc(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); + dev->button = butc; + return TRUE; +} + +_X_EXPORT Bool +InitValuatorClassDeviceStruct(DeviceIntPtr dev, int numAxes, + ValuatorMotionProcPtr motionProc, + int numMotionEvents, int mode) +{ + int i; + + ValuatorClassPtr valc; + + valc = malloc(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) +{ + FocusClassPtr focc; + + focc = malloc(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) +{ + KbdFeedbackPtr feedc; + + feedc = malloc(sizeof(KbdFeedbackClassRec)); + if (!feedc) + return FALSE; + feedc->BellProc = bellProc; + feedc->CtrlProc = controlProc; + feedc->ctrl = defaultKeyboardControl; + feedc->ctrl.id = 0; + if ((feedc->next = dev->kbdfeed) != 0) + feedc->ctrl.id = dev->kbdfeed->ctrl.id + 1; + dev->kbdfeed = feedc; + (*dev->kbdfeed->CtrlProc) (dev, &dev->kbdfeed->ctrl); + return TRUE; +} + +_X_EXPORT Bool +InitPtrFeedbackClassDeviceStruct(DeviceIntPtr dev, PtrCtrlProcPtr controlProc) +{ + PtrFeedbackPtr feedc; + + feedc = malloc(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; +} + +_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; + } + + /* 0 is the server client */ + for (i = 1; i < currentMaxClients; i++) { + if (clients[i] && clients[i]->clientState == ClientStateRunning) { + 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) +{ + 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) +DeviceIntPtr dev; + +CARD8 *map1, *map2; + +int per1, per2; +{ + int i, j, k; + + 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; + + int i; + + DeviceIntPtr keybd = inputInfo.keyboard; + + 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; + } + } + + + 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 = malloc(inputMapLen); + if (!map && inputMapLen) + return BadAlloc; + if (keyc->modifierKeyMap) + free(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 = {0}; + + 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; + + 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; + } + 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; + + 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 = {0}; + + 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 */ + 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; + 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; + } + 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++; + 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; + (*keybd->kbdfeed->CtrlProc) (keybd, &keybd->kbdfeed->ctrl); + return Success; +#undef DO_ALL +} + +int +ProcGetKeyboardControl(ClientPtr client) +{ + int i; + + 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) +{ + 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; + (*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) +{ + 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; + for (i = 0; i < 32; i++) + rep.map[i] = down[i]; + WriteReplyToClient(client, sizeof(xQueryKeymapReply), &rep); + return Success; +} diff --git a/dix/dispatch.c b/dix/dispatch.c new file mode 100644 index 0000000..698ee87 --- /dev/null +++ b/dix/dispatch.c @@ -0,0 +1,3865 @@ +/************************************************************ + +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 +#endif + + +#include "windowstr.h" +#include +#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" + +#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) + free(CurrentSelections); + CurrentSelections = (Selection *) NULL; + NumCurrentSelections = 0; +} + +void +FlushClientCaches(XID id) +{ + int i; + + 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 7 /* ms */ +#define SMART_SCHEDULE_MAX_SLICE 20 /* 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); + +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) +{ + int *clientReady; /* array of request ready clients */ + + int result; + + ClientPtr client; + + int nready; + + 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 + result = (*client->requestVector[MAJOROP]) (client); + + if (result != Success) { + if (client->noClientException != Success) + CloseDownClient(client); + else + SendErrorToClient(client, MAJOROP, + MinorOpcodeOfRequest(client), + client->errorValue, result); + break; + } + } + FlushAllOutput(); +#ifdef SMART_SCHEDULE + client = clients[clientReady[nready]]; + if (client) + client->smart_stop_tick = SmartScheduleTime; +#endif + requestingClient = NULL; + } + dispatchException &= ~DE_PRIORITYCHANGE; + } + KillAllClients(); + DEALLOCATE_LOCAL(clientReady); + dispatchException &= ~DE_RESET; + ResetOsBuffers(); +} + +#undef MAJOROP + +_X_EXPORT int +ProcBadRequest(ClientPtr client) +{ + return (BadRequest); +} + +int +ProcCreateWindow(ClientPtr client) +{ + 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) +{ + WindowPtr pWin; + + REQUEST(xChangeWindowAttributesReq); + 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) +{ + WindowPtr pWin; + + REQUEST(xResourceReq); + xGetWindowAttributesReply wa = {0}; + + 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) +{ + 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) +{ + 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) +{ + WindowPtr pWin; + + REQUEST(xChangeSaveSetReq); + 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) +{ + WindowPtr pWin, pParent; + + REQUEST(xReparentWindowReq); + 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) +{ + 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) +{ + 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) +{ + 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) +{ + 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) +{ + WindowPtr pWin; + + REQUEST(xConfigureWindowReq); + 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) +{ + 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) +{ + 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))) { + 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 = {0}; + + 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; + + 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 = {0}; + + 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); + } +} + + +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 = malloc(sizeof(Selection)); + else + newsels = (Selection *) realloc(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) + ) { + 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); + + 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) { + BoxRec box; + 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)) + /* When a window is shaped, a further check + * is made to see if the point is inside + * borderSize + */ + && (!wBoundingShape(pWin) || + POINT_IN_REGION( + &pWin->borderSize, x, y, &box)) + + && (!wInputShape(pWin) || + POINT_IN_REGION( + wInputShape(pWin), + x - pWin->drawable.x, + y - pWin->drawable.y, &box)) + ) { + 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; + + 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; + + DrawablePtr pDraw; + + REQUEST(xCreatePixmapReq); + DepthPtr pDepth; + + 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; + + 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) +{ + GC *dstGC; + + 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) +{ + 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; + + 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) +{ + 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); + 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) +{ + DrawablePtr pDst; + + DrawablePtr pSrc; + + 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(pRgn); + } + + return (client->noClientException); +} + +int +ProcCopyPlane(register ClientPtr client) +{ + DrawablePtr psrcDraw, pdstDraw; + + 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(pRgn); + } + return (client->noClientException); +} + +int +ProcPolyPoint(register ClientPtr client) +{ + int npoint; + + GC *pGC; + + 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; + + GC *pGC; + + 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; + + GC *pGC; + + 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; + + GC *pGC; + + 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; + + GC *pGC; + + 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; + + GC *pGC; + + 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; + + GC *pGC; + + 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; + + GC *pGC; + + 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) +{ + GC *pGC; + + 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) +{ + DrawablePtr pDraw; + + int nlines, linesPerBuf; + + int linesDone; + + long widthBytesLine, length; + + Mask plane = 0; + + char *pBuf; + + xGetImageReply xgi; + + + 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 = malloc(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); + } + + + 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); + + /* 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); + + /* 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; + } + } + } + } + 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; + + DrawablePtr pDraw; + + 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; + + DrawablePtr pDraw; + + 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; + + 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 = {0}; + + 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); + } + 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); + } + 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); + } + { + 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; + { + 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 = {0}; + + count = ((client->req_len << 2) - sizeof(xQueryColorsReq)) >> 2; + prgbs = (xrgb *) ALLOCATE_LOCAL(count * sizeof(xrgb)); + memset(prgbs, 0, 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 = {0}; + + 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; + + PixmapPtr src; + + 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 = malloc(n); + if (!srcbits) + return (BadAlloc); + mskbits = malloc(n); + if (!mskbits) { + free(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) { + 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 = {0}; + + 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); + 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); + } + free(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); +} + +/********************** + * 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 + free(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() +{ + int i; + + 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; + client->replyBytesRemaining = 0; + 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) +{ + char *ptr; + + DevUnion *ppriv; + + unsigned *sizes; + + unsigned size; + + int i; + + if (totalClientSize == sizeof(ClientRec)) + ppriv = (DevUnion *) NULL; + else if (client->index) + ppriv = (DevUnion *) (client + 1); + else { + ppriv = malloc(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) +{ + int i; + + ClientPtr client; + + xReq data; + + i = nextFreeClientID; + if (i == MAXCLIENTS) + return (ClientPtr) NULL; + clients[i] = client = malloc(totalClientSize); + if (!client) + return (ClientPtr) NULL; + InitClient(client, i, ospriv); + InitClientPrivates(client); + if (!InitClientResources(client)) { + free(client); + return (ClientPtr) NULL; + } + data.reqType = 1; + data.length = (sz_xReq + sz_xConnClientPrefix) >> 2; + if (!InsertFakeRequest(client, (char *) &data, sz_xReq)) { + FreeClientResources(client); + free(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); + 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); + } + ResetCurrentRequest(client); + return (client->noClientException); +} + +int +SendConnSetup(register ClientPtr client, const char *reason) +{ + xWindowRoot *root; + + 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; + ((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); + + for (i = 0; i < numScreens; i++) { + unsigned int j; + + 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) +{ + const char *reason; + char *auth_proto, *auth_string; + + 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) +{ + 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) +{ + 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/dix/dispatch.h b/dix/dispatch.h new file mode 100644 index 0000000..4b71b5a --- /dev/null +++ b/dix/dispatch.h @@ -0,0 +1,146 @@ +/************************************************************ + +Copyright 1996 by Thomas E. Dickey + + 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 +#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/dix/dixfonts.c b/dix/dixfonts.c new file mode 100644 index 0000000..b3ed865 --- /dev/null +++ b/dix/dixfonts.c @@ -0,0 +1,2053 @@ +/************************************************************************ +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 +#endif + +#include +#include +#include +#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 XF86BIGFONT +#define _XF86BIGFONT_SERVER_ +#include +#include "xf86bigfontsrv.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) { + + + return; + } + } + if (num_slept_fpes == size_slept_fpes) { + new = (FontPathElementPtr *) + realloc(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); + free(fpe->name); + free(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 *) realloc(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]); + } + free(c->fpe_list); + free(c->fontname); + free(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 = malloc(lenfname + 1); + memmove(f, pfontname, lenfname); + f[lenfname] = '\0'; + ErrorF("OpenFont: fontname is \"%s\"\n", f); + free(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 = malloc(sizeof(OFclosureRec)); + if (!c) + return BadAlloc; + c->fontname = malloc(lenfname); + c->origFontName = pfontname; + c->origFontNameLen = lenfname; + if (!c->fontname) { + free(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 *) + malloc(sizeof(FontPathElementPtr) * num_fpes); + if (!c->fpe_list) { + free(c->fontname); + free(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); + + 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) + free(resolved); + resolved = malloc(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) + free(c->savedName); + c->savedName = malloc(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]); + free(c->fpe_list); + if (c->savedName) + free(c->savedName); + FreeFontNames(names); + free(c); + if (resolved) + free(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 = malloc(sizeof *c))) + return BadAlloc; + c->fpe_list = (FontPathElementPtr *) + malloc(sizeof(FontPathElementPtr) * num_fpes); + if (!c->fpe_list) { + free(c); + return BadAlloc; + } + c->names = MakeFontNamesRecord(max_names < 100 ? max_names : 100); + if (!c->names) { + free(c->fpe_list); + free(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) + free(c->savedName); + c->savedName = malloc(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 *) realloc(c->reply, length); + if (!reply) { + err = AllocError; + goto bail; + } + 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) { + free(fontInfo.props); + free(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 (err == AllocError && c->client != serverClient) { + SendErrorToClient(c->client, X_ListFontsWithInfo, 0, + 0, FontToXError(err)); + } + if (c->slept) + ClientWakeup(client); + for (i = 0; i < c->num_fpes; i++) + FreeFPE(c->fpe_list[i]); + free(c->reply); + free(c->fpe_list); + if (c->savedName) + free(c->savedName); + free(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 = malloc(sizeof *c))) + goto badAlloc; + c->fpe_list = (FontPathElementPtr *) + malloc(sizeof(FontPathElementPtr) * num_fpes); + if (!c->fpe_list) { + free(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) +{ + FontPtr pFont = c->pGC->font, oldpFont; + + Font fid; + + 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; + + 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; + + /* 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 = malloc(sizeof(PTclosureRec)); + if (!new_closure) { + err = BadAlloc; + goto bail; + } + *new_closure = *c; + + len = new_closure->endReq - new_closure->pElt; + new_closure->data = malloc(len); + if (!new_closure->data) { + free(new_closure); + err = BadAlloc; + goto bail; + } + memmove(new_closure->data, new_closure->pElt, len); + new_closure->pElt = new_closure->data; + new_closure->endReq = new_closure->pElt + len; + + /* Step 2 */ + + pGC = GetScratchGC(new_closure->pGC->depth, new_closure->pGC->pScreen); + if (!pGC) { + free(new_closure->data); + free(new_closure); + err = BadAlloc; + goto bail; + } + if ((err = CopyGC(new_closure->pGC, pGC, GCFunction | + GCPlaneMask | GCForeground | + GCBackground | GCFillStyle | + GCTile | GCStipple | + GCTileStipXOrigin | + GCTileStipYOrigin | GCFont | + GCSubwindowMode | GCClipXOrigin | + GCClipYOrigin | GCClipMask)) != Success) { + FreeScratchGC(pGC); + free(new_closure->data); + free(new_closure); + err = BadAlloc; + goto bail; + } + c = new_closure; + 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) { + 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); + free(c->data); + free(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; + ITclosurePtr old_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 = malloc(sizeof(ITclosureRec)); + if (!new_closure) { + err = BadAlloc; + goto bail; + } + old_closure = c; + *new_closure = *c; + c = new_closure; + + data = malloc(c->nChars * c->itemSize); + if (!data) { + free(c); + c = old_closure; + 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) { + free(c->data); + free(c); + c = old_closure; + 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); + free(c->data); + free(c); + c = old_closure; + 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); + free(c->data); + free(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) { + list[i]->refcount = found; /* ensure it will get freed */ + } + } + FreeFPE(list[i]); + } + free((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 *) + malloc(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 = malloc(sizeof(FontPathElementRec)); + if (!fpe) { + err = BadAlloc; + goto bail; + } + fpe->name = malloc(len + 1); + if (!fpe->name) { + free(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); + } + free(fpe->name); + free(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]); + free(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 *) realloc(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(); + + { +#ifdef KDRIVESERVER + BuiltinRegisterFpeFunctions(); +#endif + FontFileRegisterFpeFunctions(); + } +} + +_X_EXPORT +int +GetDefaultPointSize() +{ + return 120; +} + +_X_EXPORT +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 + */ + +_X_EXPORT +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 *) realloc(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; + free(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); +} + +_X_EXPORT +Font +GetNewFontClientID() +{ + return FakeClientID(0); +} + +_X_EXPORT +int +StoreFontClientFont(FontPtr pfont, Font id) +{ + return AddResource(id, RT_NONE, (pointer) pfont); +} + +_X_EXPORT +void +DeleteFontClientID(Font id) +{ + FreeResource(id, RT_NONE); +} + +_X_EXPORT +int +client_auth_generation(ClientPtr client) +{ + return 0; +} + +static int fs_handlers_installed = 0; + +static unsigned int last_server_gen; + +_X_EXPORT +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) { + + + if (!RegisterBlockAndWakeupHandlers(block_handler, + FontWakeup, (pointer) 0)) + return AllocError; + fs_handlers_installed++; + } + QueueFontWakeup(fpe); + return Successful; +} + +_X_EXPORT +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) { + + + RemoveBlockAndWakeupHandlers(block_handler, FontWakeup, + (pointer) 0); + } + } + RemoveFontWakeup(fpe); +} + diff --git a/dix/dixutils.c b/dix/dixutils.c new file mode 100644 index 0000000..17faa93 --- /dev/null +++ b/dix/dixutils.c @@ -0,0 +1,837 @@ +/*********************************************************** + +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 +#endif + +#include +#include +#include "misc.h" +#include "windowstr.h" +#include "dixstruct.h" +#include "pixmapstr.h" +#include "scrnintstr.h" +#define XK_LATIN1 +#include + +/* + * 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; +} + +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; +} + + +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) +{ + 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; +} + + +_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 *) realloc(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 *) realloc(client->saveSet, + sizeof(*pTmp) * numnow); + if (pTmp) + client->saveSet = pTmp; + } + else { + free(client->saveSet); + client->saveSet = (SaveSetElt *) NULL; + } + client->numSaved = numnow; + return (Success); + } + return (Success); +} + +void +DeleteWindowFromAnySaveSet(WindowPtr pWin) +{ + int i; + + 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) +{ + 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) +{ + 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) realloc(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() +{ + free(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 */ + free(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 */ + free(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 = malloc(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 = malloc(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; + free(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 = malloc(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; + free(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; + free(pcbr->next); + pcbr->next = cbr; + } + else { + cbr = cbr->next; + free(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; + free(cbr); + } + free(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 = malloc(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 **) realloc(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) + free(listsToCleanup); + + numCallbackListsToCleanup = 0; + listsToCleanup = NULL; +} diff --git a/dix/events.c b/dix/events.c new file mode 100644 index 0000000..9cf8172 --- /dev/null +++ b/dix/events.c @@ -0,0 +1,3437 @@ +/************************************************************ + +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 +#endif + +#include +#include "misc.h" +#include "resource.h" +#include +#include "windowstr.h" +#include "inputstr.h" +#include "scrnintstr.h" +#include "cursorstr.h" + +#include "dixstruct.h" +#include "globals.h" + + + + +#include +#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 ButtonMotionMasks are equal + * to the corresponding ButtonMasks 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 */ + RegionPtr hotShape; /* additional logical shape constraint */ + BoxRec physLimits; /* physical constraints of hot spot */ + WindowPtr win; /* window of logical position */ + HotSpot hot; /* logical pointer position */ + HotSpot hotPhys; /* physical pointer position */ +} sprite; /* info about the cursor sprite */ + + +static void DoEnterLeaveEvents(WindowPtr fromWin, WindowPtr toWin, int mode); + +static WindowPtr XYToWindow(int x, int y); + +extern int lastEvent; + +static Mask lastEventMask; + + +#define CantBeFiltered NoEventMask +static Mask filters[128]; + +static const Mask initialFilters[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 */ +}; + + +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; + + 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); +} + +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(shape, x, y, &box)) + return; + box = *REGION_EXTENTS(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(shape, x, y, &box)); + *px = x; + *py = y; +} + +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; + if (sprite.hotShape) + ConfineToShape(sprite.hotShape, &new.x, &new.y); + 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) +{ + 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->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; + if (wBoundingShape(pWin)) + ConfineToShape(&pWin->borderSize, &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; + } + } + ROOT = WindowTable[sprite.hot.pScreen->myNum]; +} + +static void +ConfineCursorToWindow(WindowPtr pWin, Bool generateEvents, Bool confineToScreen) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + + + if (syncEvents.playingEvents) { + CheckVirtualMotion((QdEventPtr) NULL, pWin); + SyntheticMotion(sprite.hot.x, sprite.hot.y); + } + else { + sprite.hotLimits = *REGION_EXTENTS(&pWin->borderSize); + sprite.hotShape = wBoundingShape(pWin) ? &pWin->borderSize : NullRegion; + CheckPhysLimits(sprite.current, generateEvents, confineToScreen, + pScreen); + } +} + +_X_EXPORT Bool +PointerConfinedToScreen() +{ + return sprite.confined; +} + +static void +ChangeToCursor(CursorPtr cursor) +{ + + 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) +{ + WindowPtr win; + + 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; +} + + +#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) +{ + QdEventPtr tail = *syncEvents.pendtail; + + QdEventPtr qe; + + xEvent *qxE; + + NoticeTime(xE); + + + 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) { + 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 = malloc(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) +{ + QdEventPtr *prev, qe; + + 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; + (*qe->device->public.processInputProc) (qe->event, qe->device, + qe->evcount); + free(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() +{ + DeviceIntPtr replayDev = syncEvents.replayDev; + + int i; + + WindowPtr w; + + xEvent *xE; + + int count; + + GrabPtr grab; + + 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(); +} + +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); +} + +void +CheckGrabForSyncs(register DeviceIntPtr thisDev, Bool thisMode, Bool otherMode) +{ + GrabPtr grab = thisDev->grab; + + 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) +{ + GrabPtr grab = mouse->grab; + + 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) +{ + GrabPtr grab = keybd->grab; + + DeviceIntPtr dev; + + 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; + + 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) +{ + 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; + } + } + 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; + + 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; + + 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. +*/ + + +int +MaybeDeliverEventsToClient(register WindowPtr pWin, xEvent *pEvents, + int count, Mask filter, ClientPtr dontClient) +{ + OtherClients *other; + + if (pWin->eventMask & filter) { + if (wClient(pWin) == dontClient) + return 0; + 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; + 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) { + 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; + + + 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->borderSize, x, y, &box)) + return TRUE; + + return FALSE; +} + +static WindowPtr +XYToWindow(int x, int y) +{ + 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)) + /* 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( + wInputShape(pWin), + x - pWin->drawable.x, + y - pWin->drawable.y, &box)) + ) { + if (spriteTraceGood >= spriteTraceSize) { + spriteTraceSize += 10; + Must_have_memory = TRUE; /* XXX */ + spriteTrace = + (WindowPtr *) realloc(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; + + + 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; + 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)) { + (*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; + } + + 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); +} + + +void +DefineInitialRootWindow(register WindowPtr win) +{ + 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; + 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); + +} + +/* + * 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; + if (newScreen != sprite.hotPhys.pScreen) + ConfineCursorToWindow(WindowTable[newScreen->myNum], TRUE, FALSE); +} + + +int +ProcWarpPointer(ClientPtr client) +{ + WindowPtr dest = NULL; + + int x, y; + + ScreenPtr newScreen; + + REQUEST(xWarpPointerReq); + + REQUEST_SIZE_MATCH(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->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 (sprite.hotShape) + ConfineToShape(sprite.hotShape, &x, &y); + (*newScreen->SetCursorPosition) (newScreen, x, y, TRUE); + } + else if (!PointerConfinedToScreen()) { + NewCurrentScreen(newScreen, x, y); + } + return Success; +} + +static Bool +BorderSizeNotEmpty(WindowPtr pWin) +{ + if (REGION_NOTEMPTY(&pWin->borderSize)) + return TRUE; + + 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) +{ + GrabPtr grab = wPassiveGrabs(pWin); + + GrabRec tempGrab; + + 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) { + tempGrab.modifierDevice = grab->modifierDevice; + if ((device == grab->modifierDevice) && ((xE->u.u.type == KeyPress) + )) + tempGrab.modifiersDetail.exact = + grab->modifierDevice->key->prev_state; + else + tempGrab.modifiersDetail.exact = + grab->modifierDevice->key->state; + if (GrabMatchesSecond(&tempGrab, grab) && + (!grab->confineTo || + (grab->confineTo->realized && + BorderSizeNotEmpty(grab->confineTo)))) { + (*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 *) realloc(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) +{ + int i; + + WindowPtr pWin = NULL; + + FocusClassPtr focus = device->focus; + + if (((xE->u.u.type == ButtonPress) + ) && (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) +{ + GrabPtr grab = thisDev->grab; + + int deliveries = 0; + + DeviceIntPtr dev; + + 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 + )) + thisDev->valuator->motionHintWindow = grab->window; + } + if (deliveries && !deactivateGrab && (xE->u.u.type != MotionNotify + )) + 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 *) realloc(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 +ProcessKeyboardEvent(register xEvent *xE, register DeviceIntPtr keybd, + int count) +{ + int key, bit; + + BYTE *kptr; + + int i; + + CARD8 modifiers; + + CARD16 mask; + + GrabPtr grab = keybd->grab; + + Bool deactivateGrab = FALSE; + + KeyClassPtr keyc = keybd->key; + + + if (!syncEvents.playingEvents) { + NoticeTime(xE); + if (DeviceEventCallback) { + DeviceEventInfoRec eventinfo; + + eventinfo.events = xE; + eventinfo.count = count; + CallCallbacks(&DeviceEventCallback, (pointer) &eventinfo); + } + } + 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]; + +#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); + +} + + +void +ProcessPointerEvent(register xEvent *xE, register DeviceIntPtr mouse, int count) +{ + GrabPtr grab = mouse->grab; + + Bool deactivateGrab = FALSE; + + ButtonClassPtr butc = mouse->button; + + + if (!syncEvents.playingEvents) + NoticeTime(xE) + XE_KBPTR.state = (butc->state | ( + inputInfo.keyboard->key->state + )); + { + 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) { + int key; + + 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) +WindowPtr pWin; +{ + OtherClients *others; + + 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) +{ + OtherClientsPtr other, prev; + + 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); + } + free(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; + pWin->eventMask = mask; + } + else { + for (others = wOtherClients(pWin); others; others = others->next) { + if (SameClient(others, client)) { + check = others->mask; + 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 = malloc(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) +{ + 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; + + DeviceIntPtr keybd = inputInfo.keyboard; + + WindowPtr focus; + + DeviceIntPtr mouse = inputInfo.pointer; + + 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; + 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; + + 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) +{ + 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; + + 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; + + 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) +{ + 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 */ + 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 */ + 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); + 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) +{ + FocusClassPtr focus; + + 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; + + 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 *) realloc(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); + return SetInputFocus(client, inputInfo.keyboard, stuff->focus, + stuff->revertTo, stuff->time, FALSE); +} + +int +ProcGetInputFocus(ClientPtr client) +{ + xGetInputFocusReply rep = {0}; + + /* 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; + + 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) +{ + WindowPtr pWin; + + 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); + 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; + } + + + 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; + + memcpy(filters, initialFilters, 128 * sizeof(Mask)); + + if (spriteTraceSize == 0) { + spriteTraceSize = 32; + spriteTrace = malloc(32 * sizeof(WindowPtr)); + if (!spriteTrace) + FatalError("failed to allocate spriteTrace"); + } + spriteTraceGood = 0; + lastEventMask = OwnerGrabButtonMask; + filters[MotionNotify] = PointerMotionMask; + 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; + + free(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) +{ + free(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); + } +} + +/** + * 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; + + + 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) +{ + 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]; + 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) +{ + xEvent eventTo, *eventFrom; + + int i; + + + + 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/dix/extension.c b/dix/extension.c new file mode 100644 index 0000000..89bb66e --- /dev/null +++ b/dix/extension.c @@ -0,0 +1,404 @@ +/*********************************************************** + +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 +#endif + +#include +#include +#include "misc.h" +#include "dixstruct.h" +#include "extnsionst.h" +#include "gcstruct.h" +#include "scrnintstr.h" +#include "dispatch.h" + +#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) +{ + char *ptr; + + DevUnion *ppriv; + + unsigned *sizes; + + unsigned size; + + 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; + + 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 = malloc(totalExtensionSize); + if (!ext) + return ((ExtensionEntry *) NULL); + bzero(ext, totalExtensionSize); + InitExtensionPrivates(ext); + ext->name = malloc(strlen(name) + 1); + ext->num_aliases = 0; + ext->aliases = (char **) NULL; + if (!ext->name) { + free(ext); + return ((ExtensionEntry *) NULL); + } + strcpy(ext->name, name); + i = NumExtensions; + newexts = (ExtensionEntry **) realloc(extensions, + (i + 1) * sizeof(ExtensionEntry *)); + if (!newexts) { + free(ext->name); + free(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); +} + +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); +} + +_X_EXPORT void +DeclareExtensionSecurity(char *extname, Bool secure) +{ +} + +_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() +{ + int i, j; + + for (i = NumExtensions - 1; i >= 0; i--) { + (*extensions[i]->CloseDown) (extensions[i]); + NumExtensions = i; + free(extensions[i]->name); + for (j = extensions[i]->num_aliases; --j >= 0;) + free(extensions[i]->aliases[j]); + free(extensions[i]->aliases); + free(extensions[i]); + } + free(extensions); + extensions = (ExtensionEntry **) NULL; + lastEvent = EXTENSION_EVENT_BASE; + lastError = FirstExtensionError; + for (i = 0; i < MAXSCREENS; i++) { + ScreenProcEntry *spentry = &AuxillaryScreenProcs[i]; + + while (spentry->num) { + spentry->num--; + free(spentry->procList[spentry->num].name); + } + free(spentry->procList); + spentry->procList = (ProcEntryPtr) NULL; + } +} + +int +ProcQueryExtension(ClientPtr client) +{ + xQueryExtensionReply reply = {0}; + + 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 + ) + 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 = {0}; + + 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) { + int i, j; + + for (i = 0; i < NumExtensions; i++) { + 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; + + *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) +{ + int i; + + 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) +{ + ScreenProcEntry *spentry; + + 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 = malloc(strlen(name) + 1); + if (!newname) + return FALSE; + procEntry = (ProcEntryPtr) + realloc(spentry->procList, + sizeof(ProcEntryRec) * (spentry->num + 1)); + if (!procEntry) { + free(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/dix/ffs.c b/dix/ffs.c new file mode 100644 index 0000000..1e75076 --- /dev/null +++ b/dix/ffs.c @@ -0,0 +1,39 @@ +/* + +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; + + if (i == 0) + return 0; + for (j = 1; (i & 1) == 0; j++) + i >>= 1; + return j; +} diff --git a/dix/gc.c b/dix/gc.c new file mode 100644 index 0000000..2e0e051 --- /dev/null +++ b/dix/gc.c @@ -0,0 +1,1275 @@ +/*********************************************************** + +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 +#endif + +#include +#include +#include +#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 + +extern XID clientErrorValue; + +extern FontPtr defaultFont; + +static Bool CreateDefaultTile(GCPtr pGC); + +static 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) +{ + BITS32 index2; + + 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) { + free(pGC->dash); + pGC->numInDashList = 2; + pGC->dash = DefaultDash; + } + } + else if (newdash != 0) { + unsigned char *dash; + + dash = malloc(2 * sizeof(unsigned char)); + if (dash) { + if (pGC->dash != DefaultDash) + free(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; + + char *ptr; + + DevUnion *ppriv; + + unsigned *sizes; + + unsigned size; + + int i; + + pGC = malloc(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) +{ + 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) +{ + 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) { + free(pgcDst->dash); + pgcDst->numInDashList = pgcSrc->numInDashList; + pgcDst->dash = pgcSrc->dash; + } + } + else { + unsigned char *dash; + + unsigned int i; + + dash = malloc(pgcSrc->numInDashList * + sizeof(unsigned char)); + if (dash) { + if (pgcDst->dash != DefaultDash) + free(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) + free(pGC->dash); + free(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) +{ + 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) +{ + int i; + + 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) +{ + int i; + + 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) +{ + 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) +{ + long i; + + 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 = malloc(2 * ndash * sizeof(unsigned char)); + else + p = malloc(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) + free(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) +{ + xRectangle *prectP, *prectN; + + 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 = malloc(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) +{ + int i; + + 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) +{ + ScreenPtr pScreen = pGC->pScreen; + + 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/dix/globals.c b/dix/globals.c new file mode 100644 index 0000000..6b17073 --- /dev/null +++ b/dix/globals.c @@ -0,0 +1,176 @@ +/************************************************************ + +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 +#endif + +#include +#include +#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[MAXCLIENTS]; +_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[MAXSCREENS]; + +_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 + +_X_EXPORT CARD16 DPMSPowerLevel = 0; + +_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 *defaultDisplayClass = COMPILEDDISPLAYCLASS; + +FontPtr defaultFont; /* not declared in dix.h to avoid including font.h in + every compilation of dix code */ +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; + +DDXPointRec dixScreenOrigins[MAXSCREENS]; diff --git a/dix/glyphcurs.c b/dix/glyphcurs.c new file mode 100644 index 0000000..3278735 --- /dev/null +++ b/dix/glyphcurs.c @@ -0,0 +1,194 @@ +/************************************************************************ + +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 +#endif + +#include "misc.h" +#include +#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) +{ + ScreenPtr pScreen; + + 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 = malloc(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); + free(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/dix/grabs.c b/dix/grabs.c new file mode 100644 index 0000000..a21343c --- /dev/null +++ b/dix/grabs.c @@ -0,0 +1,404 @@ +/* + +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 +#endif + +#include +#include "misc.h" +#include +#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 = malloc(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) + free(pGrab->modifiersDetail.pMask); + + if (pGrab->detail.pMask != NULL) + free(pGrab->detail.pMask); + + if (pGrab->cursor) + FreeCursor(pGrab->cursor, (Cursor) 0); + + free(pGrab); +} + +int +DeletePassiveGrab(pointer value, XID id) +{ + 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) +{ + Mask *mask; + + int i; + + mask = malloc(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) +{ + 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++) + free(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++) { + free(*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/dix/initatoms.c b/dix/initatoms.c new file mode 100644 index 0000000..110e0be --- /dev/null +++ b/dix/initatoms.c @@ -0,0 +1,153 @@ +/* THIS IS A GENERATED FILE + * + * Do not change! Changing this file implies a protocol change! + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#include +#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/dix/main.c b/dix/main.c new file mode 100644 index 0000000..a2c3a25 --- /dev/null +++ b/dix/main.c @@ -0,0 +1,661 @@ +/*********************************************************** + +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 +#endif + +#include +#include /* for unistd.h */ +#include +#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 +#include "opaque.h" +#include "servermd.h" +#include "site.h" +#include "dixfont.h" +#include "extnsionst.h" +#include "dixevents.h" /* InitEvents() */ + +#ifdef DPMSExtension +#define DPMS_SERVER +#include +#include "dpmsproc.h" +#endif + +extern int InitClientPrivates(ClientPtr client); + +extern void Dispatch(void); + +char *ConnectionInfo; + +xConnSetupPrefix connSetupPrefix; + +extern FontPtr defaultFont; + +extern int screenPrivateCount; + +extern Bool CreateGCperDepthArray(void); + +static +Bool CreateConnectionBlock(void); + +static void FreeScreen(ScreenPtr); + +_X_EXPORT PaddingInfo PixmapWidthPaddingInfo[33]; + +int connBlockScreenStart; + +_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; + + char *xauthfile; + + HWEventQueueType alwaysCheckForInput[2]; + + display = "0"; + + /* 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. */ + + CheckUserParameters(argc, argv, envp); + + CheckUserAuthorization(); + + + InitConnectionLimits(); + + /* 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 = DEFAULT_SCREEN_SAVER_TIME; + DPMSSuspendTime = DEFAULT_SCREEN_SAVER_TIME; + DPMSOffTime = DEFAULT_SCREEN_SAVER_TIME; + DPMSEnabled = TRUE; + DPMSPowerLevel = 0; +#endif + InitBlockAndWakeupHandlers(); + /* Perform any operating system dependent initializations you'd like */ + OsInit(); + if (serverGeneration == 1) { + CreateWellKnownSockets(); + for (i = 1; i < MAXCLIENTS; i++) + clients[i] = NullClient; + serverClient = malloc(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.numScreens = 0; + + InitAtoms(); + InitEvents(); + InitGlyphCaching(); + ResetExtensionPrivates(); + ResetClientPrivates(); + ResetScreenPrivates(); + ResetWindowPrivates(); + ResetGCPrivates(); + ResetPixmapPrivates(); + ResetColormapPrivates(); + ResetFontPrivateIndex(); + ResetDevicePrivateIndex(); + InitCallbackManager(); + InitVisualWrap(); + InitOutput(&screenInfo, argc, argv); + + if (screenInfo.numScreens < 1) + FatalError("no screens found"); + 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 (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 + + + for (i = 0; i < screenInfo.numScreens; i++) + InitRootWindow(WindowTable[i]); + DefineInitialRootWindow(WindowTable[0]); + SaveScreens(SCREEN_SAVER_FORCER, ScreenSaverReset); + + { + 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(); + + FreeAllResources(); + + memset(WindowTable, 0, sizeof(WindowTable)); + 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(); + FreeFonts(); + + free(serverClient->devPrivates); + serverClient->devPrivates = NULL; + + if (dispatchException & DE_TERMINATE) { + CloseWellKnownConnections(); + } + + OsCleanup((dispatchException & DE_TERMINATE) != 0); + + if (dispatchException & DE_TERMINATE) { + ddxGiveUp(); + break; + } + + free(ConnectionInfo); + ConnectionInfo = NULL; + } + return (0); +} + +static const int VendorRelease = VENDOR_RELEASE; +static const char * const VendorString = VENDOR_STRING; + +static const int padlength[4] = { 0, 3, 2, 1 }; + +static + Bool +CreateConnectionBlock() +{ + xConnSetup setup; + xWindowRoot root; + xDepth depth; + xVisualType visual; + xPixmapFormat format; + unsigned long vid; + int i, j, k, lenofblock, sizesofar = 0; + char *pBuf; + + memset(&setup, 0, sizeof(xConnSetup)); + + /* 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 = malloc(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; + + memset(&format, 0, sizeof(xPixmapFormat)); + 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; + memset(&depth, 0, sizeof(xDepth)); + memset(&visual, 0, sizeof(xVisualType)); + 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 = FALSE; + 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 *) realloc(ConnectionInfo, lenofblock); + if (!pBuf) { + free(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 = calloc(1, sizeof(ScreenRec)); + if (!pScreen) + return -1; + + pScreen->devPrivates = calloc(sizeof(DevUnion), + screenPrivateCount); + if (!pScreen->devPrivates && screenPrivateCount) { + free(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); + pScreen->PixmapPrivateLen = 0; + pScreen->PixmapPrivateSizes = (unsigned *) NULL; + pScreen->totalPixmapSize = BitmapBytePad(sizeof(PixmapRec) * 8); + 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) +{ + free(pScreen->WindowPrivateSizes); + free(pScreen->GCPrivateSizes); + free(pScreen->PixmapPrivateSizes); + free(pScreen->devPrivates); + free(pScreen); +} diff --git a/dix/pixmap.c b/dix/pixmap.c new file mode 100644 index 0000000..0071152 --- /dev/null +++ b/dix/pixmap.c @@ -0,0 +1,143 @@ +/* + +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 +#endif + +#include +#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; + + char *ptr; + + DevUnion *ppriv; + + unsigned *sizes; + + unsigned size; + + int i; + + if (pScreen->totalPixmapSize > ((size_t) - 1) - pixDataSize) + return NullPixmap; + + pPixmap = calloc(1, 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; + } + +#ifdef _XSERVER64 + if (pPixmap) { + pPixmap->drawable.pad0 = 0; + pPixmap->drawable.pad1 = 0; + } +#endif + + return pPixmap; +} diff --git a/dix/privates.c b/dix/privates.c new file mode 100644 index 0000000..91401a8 --- /dev/null +++ b/dix/privates.c @@ -0,0 +1,340 @@ +/* + +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 +#endif + +#include +#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; + free(extensionPrivateSizes); + extensionPrivateSizes = (unsigned *) NULL; + totalExtensionSize = + ((sizeof(ExtensionEntry) + sizeof(long) - + 1) / sizeof(long)) * sizeof(long); +} + +/* + * client private machinery + */ + +static int clientPrivateCount; + +int clientPrivateLen; + +unsigned *clientPrivateSizes; + +unsigned totalClientSize; + +void +ResetClientPrivates() +{ + clientPrivateCount = 0; + clientPrivateLen = 0; + free(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 *) realloc(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 *) realloc(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 *) realloc(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 *) realloc(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 + */ +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 *) realloc(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; +} + +/* + * colormap private machinery + */ + +int colormapPrivateCount; + +void +ResetColormapPrivates() +{ + colormapPrivateCount = 0; +} + +/* + * device private machinery + */ + +static int devicePrivateIndex = 0; + +void +ResetDevicePrivateIndex(void) +{ + devicePrivateIndex = 0; +} diff --git a/dix/property.c b/dix/property.c new file mode 100644 index 0000000..653da2a --- /dev/null +++ b/dix/property.c @@ -0,0 +1,610 @@ +/*********************************************************** + +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 +#endif + +#include +#include +#include "windowstr.h" +#include "propertyst.h" +#include "dixstruct.h" +#include "dispatch.h" +#include "swaprep.h" + +/***************************************************************** + * 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; + + 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; + + 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++) { + if (!ValidAtom(atoms[i]) + ) { + DEALLOCATE_LOCAL(props); + client->errorValue = atoms[i]; + return BadAtom; + } + 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); + } + + + 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 = malloc(sizeof(PropertyRec)); + if (!pProp) + return (BadAlloc); + data = malloc(totalSize); + if (!data && len) { + free(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) realloc(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) realloc(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 = malloc(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); + free(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); + free(pProp->data); + free(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; + free(pProp->data); + free(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 = {0}; + + 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); + + /* 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; + free(pProp->data); + free(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); + } + + + result = DeleteProperty(pWin, stuff->property); + if (client->noClientException != Success) + return (client->noClientException); + else + return (result); +} diff --git a/dix/resource.c b/dix/resource.c new file mode 100644 index 0000000..7120cf1 --- /dev/null +++ b/dix/resource.c @@ -0,0 +1,844 @@ +/************************************************************ + +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. + +******************************************************************/ + +/* Routines to manage various kinds of resources: + * + * CreateNewResourceType, 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. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#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" +#include + +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 *) realloc(DeleteFuncs, + (next + 1) * sizeof(DeleteType)); + if (!funcs) + return 0; + +#ifdef XResExtension + { + Atom *newnames; + + newnames = realloc(ResourceNames, (next + 1) * sizeof(Atom)); + if (!newnames) + return 0; + ResourceNames = newnames; + ResourceNames[next] = 0; + } +#endif + + lastResourceType = next; + DeleteFuncs = funcs; + DeleteFuncs[next] = deleteFunc; + return next; +} + +ClientResourceRec clientTable[MAXCLIENTS]; + +/***************** + * InitClientResources + * When a new client is created, call this to allocate space + * in resource table + *****************/ + +Bool +InitClientResources(ClientPtr client) +{ + int i, j; + + if (client == serverClient) { + lastResourceType = RT_LASTPREDEF; + lastResourceClass = RC_LASTPREDEF; + TypeMask = RC_LASTPREDEF - 1; + if (DeleteFuncs) + free(DeleteFuncs); + DeleteFuncs = malloc((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) + free(ResourceNames); + ResourceNames = malloc((lastResourceType + 1) * sizeof(Atom)); + if (!ResourceNames) + return FALSE; +#endif + } + clientTable[i = client->index].resources = + malloc(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) +{ + 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) +{ + XID id, maxid; + + ResourcePtr *resp; + + ResourcePtr res; + + 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; + + ClientResourceRec *rrec; + + 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 = malloc(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) +{ + int j; + + ResourcePtr res, next; + + ResourcePtr **tails, *resources; + + 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 = malloc(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; + free(clientTable[client].resources); + clientTable[client].resources = resources; +} + +_X_EXPORT void +FreeResource(XID id, RESTYPE skipDeleteFuncType) +{ + int cid; + + ResourcePtr res; + + ResourcePtr *prev, *head; + + 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); + free(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; + + ResourcePtr res; + + 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); + free(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; + + 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) +{ + ResourcePtr *resources; + + ResourcePtr this, next; + + int i, elements; + + 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) +{ + ResourcePtr *resources; + + ResourcePtr this, next; + + int i, elements; + + 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); + free(this); + } + else + prev = &this->next; + } + } +} + +void +FreeClientResources(ClientPtr client) +{ + ResourcePtr *resources; + + 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); + free(this); + } + } + free(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) +{ + + 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; + + 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; + } + } + return retval; +} + +_X_EXPORT pointer +SecurityLookupIDByClass(ClientPtr client, XID id, RESTYPE classes, Mask mode) +{ + int cid; + + 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; + } + } + 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/dix/strcasecmp.c b/dix/strcasecmp.c new file mode 100644 index 0000000..5ec3ddd --- /dev/null +++ b/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 +#endif + +#include +#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/dix/swaprep.c b/dix/swaprep.c new file mode 100644 index 0000000..762b21a --- /dev/null +++ b/dix/swaprep.c @@ -0,0 +1,1185 @@ +/************************************************************ + +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 +#endif + +#include +#include +#include "misc.h" +#include "dixstruct.h" +#include +#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) +{ + int i; + + size >>= 2; + for (i = 0; i < size; i++) + /* brackets are mandatory here, because "swapl" macro expands + to several statements */ + { + swapl(&pbuf[i]); + } + (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; + + 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; + + 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) +{ + swaps(&pRep->sequenceNumber); + (void) WriteToClient(pClient, size, (char *) pRep); +} + +/* Extra-large reply */ +void +SGetWindowAttributesReply(ClientPtr pClient, int size, + xGetWindowAttributesReply * pRep) +{ + swaps(&pRep->sequenceNumber); + swapl(&pRep->length); + swapl(&pRep->visualID); + swaps(&pRep->class); + swapl(&pRep->backingBitPlanes); + swapl(&pRep->backingPixel); + swapl(&pRep->colormap); + swapl(&pRep->allEventMasks); + swapl(&pRep->yourEventMask); + swaps(&pRep->doNotPropagateMask); + (void) WriteToClient(pClient, size, (char *) pRep); +} + +void +SGetGeometryReply(ClientPtr pClient, int size, xGetGeometryReply * pRep) +{ + swaps(&pRep->sequenceNumber); + swapl(&pRep->root); + swaps(&pRep->x); + swaps(&pRep->y); + swaps(&pRep->width); + swaps(&pRep->height); + swaps(&pRep->borderWidth); + (void) WriteToClient(pClient, size, (char *) pRep); +} + +void +SQueryTreeReply(ClientPtr pClient, int size, xQueryTreeReply * pRep) +{ + swaps(&pRep->sequenceNumber); + swapl(&pRep->length); + swapl(&pRep->root); + swapl(&pRep->parent); + swaps(&pRep->nChildren); + (void) WriteToClient(pClient, size, (char *) pRep); +} + +void +SInternAtomReply(ClientPtr pClient, int size, xInternAtomReply * pRep) +{ + swaps(&pRep->sequenceNumber); + swapl(&pRep->atom); + (void) WriteToClient(pClient, size, (char *) pRep); +} + +void +SGetAtomNameReply(ClientPtr pClient, int size, xGetAtomNameReply * pRep) +{ + swaps(&pRep->sequenceNumber); + swapl(&pRep->length); + swaps(&pRep->nameLength); + (void) WriteToClient(pClient, size, (char *) pRep); +} + +void +SGetPropertyReply(ClientPtr pClient, int size, xGetPropertyReply * pRep) +{ + swaps(&pRep->sequenceNumber); + swapl(&pRep->length); + swapl(&pRep->propertyType); + swapl(&pRep->bytesAfter); + swapl(&pRep->nItems); + (void) WriteToClient(pClient, size, (char *) pRep); +} + +void +SListPropertiesReply(ClientPtr pClient, int size, xListPropertiesReply * pRep) +{ + swaps(&pRep->sequenceNumber); + swapl(&pRep->length); + swaps(&pRep->nProperties); + (void) WriteToClient(pClient, size, (char *) pRep); +} + +void +SGetSelectionOwnerReply(ClientPtr pClient, int size, + xGetSelectionOwnerReply * pRep) +{ + swaps(&pRep->sequenceNumber); + swapl(&pRep->owner); + (void) WriteToClient(pClient, size, (char *) pRep); +} + +void +SQueryPointerReply(ClientPtr pClient, int size, xQueryPointerReply * pRep) +{ + swaps(&pRep->sequenceNumber); + swapl(&pRep->root); + swapl(&pRep->child); + swaps(&pRep->rootX); + swaps(&pRep->rootY); + swaps(&pRep->winX); + swaps(&pRep->winY); + swaps(&pRep->mask); + (void) WriteToClient(pClient, size, (char *) pRep); +} + +void +SwapTimecoord(xTimecoord * pCoord) +{ + swapl(&pCoord->time); + swaps(&pCoord->x); + swaps(&pCoord->y); +} + +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) +{ + swaps(&pRep->sequenceNumber); + swapl(&pRep->length); + swapl(&pRep->nEvents); + (void) WriteToClient(pClient, size, (char *) pRep); +} + +void +STranslateCoordsReply(ClientPtr pClient, int size, xTranslateCoordsReply * pRep) +{ + swaps(&pRep->sequenceNumber); + swapl(&pRep->child); + swaps(&pRep->dstX); + swaps(&pRep->dstY); + (void) WriteToClient(pClient, size, (char *) pRep); +} + +void +SGetInputFocusReply(ClientPtr pClient, int size, xGetInputFocusReply * pRep) +{ + swaps(&pRep->sequenceNumber); + swapl(&pRep->focus); + (void) WriteToClient(pClient, size, (char *) pRep); +} + +/* extra long reply */ +void +SQueryKeymapReply(ClientPtr pClient, int size, xQueryKeymapReply * pRep) +{ + swaps(&pRep->sequenceNumber); + swapl(&pRep->length); + (void) WriteToClient(pClient, size, (char *) pRep); +} + +static void +SwapCharInfo(xCharInfo * pInfo) +{ + swaps(&pInfo->leftSideBearing); + swaps(&pInfo->rightSideBearing); + swaps(&pInfo->characterWidth); + swaps(&pInfo->ascent); + swaps(&pInfo->descent); + swaps(&pInfo->attributes); +} + +static void +SwapFontInfo(xQueryFontReply * pr) +{ + swaps(&pr->minCharOrByte2); + swaps(&pr->maxCharOrByte2); + swaps(&pr->defaultChar); + swaps(&pr->nFontProps); + swaps(&pr->fontAscent); + swaps(&pr->fontDescent); + SwapCharInfo(&pr->minBounds); + SwapCharInfo(&pr->maxBounds); + swapl(&pr->nCharInfos); +} + +static void +SwapFont(xQueryFontReply * pr, Bool hasGlyphs) +{ + unsigned i; + + xCharInfo *pxci; + + unsigned nchars, nprops; + + char *pby; + + swaps(&pr->sequenceNumber); + swapl(&pr->length); + 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((int *) pby); + pby += 4; + swapl((int *) pby); + 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) +{ + swaps(&pRep->sequenceNumber); + swaps(&pRep->fontAscent); + swaps(&pRep->fontDescent); + swaps(&pRep->overallAscent); + swaps(&pRep->overallDescent); + swapl(&pRep->overallWidth); + swapl(&pRep->overallLeft); + swapl(&pRep->overallRight); + (void) WriteToClient(pClient, size, (char *) pRep); +} + +void +SListFontsReply(ClientPtr pClient, int size, xListFontsReply * pRep) +{ + swaps(&pRep->sequenceNumber); + swapl(&pRep->length); + swaps(&pRep->nFonts); + (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) +{ + swaps(&pRep->sequenceNumber); + swapl(&pRep->length); + swaps(&pRep->nPaths); + (void) WriteToClient(pClient, size, (char *) pRep); +} + +void +SGetImageReply(ClientPtr pClient, int size, xGetImageReply * pRep) +{ + swaps(&pRep->sequenceNumber); + swapl(&pRep->length); + swapl(&pRep->visual); + (void) WriteToClient(pClient, size, (char *) pRep); + /* Fortunately, image doesn't need swapping */ +} + +void +SListInstalledColormapsReply(ClientPtr pClient, int size, + xListInstalledColormapsReply * pRep) +{ + swaps(&pRep->sequenceNumber); + swapl(&pRep->length); + swaps(&pRep->nColormaps); + (void) WriteToClient(pClient, size, (char *) pRep); +} + +void +SAllocColorReply(pClient, size, pRep) +ClientPtr pClient; + +int size; + +xAllocColorReply *pRep; +{ + swaps(&pRep->sequenceNumber); + swaps(&pRep->red); + swaps(&pRep->green); + swaps(&pRep->blue); + swapl(&pRep->pixel); + (void) WriteToClient(pClient, size, (char *) pRep); +} + +void +SAllocNamedColorReply(ClientPtr pClient, int size, xAllocNamedColorReply * pRep) +{ + swaps(&pRep->sequenceNumber); + swapl(&pRep->pixel); + swaps(&pRep->exactRed); + swaps(&pRep->exactGreen); + swaps(&pRep->exactBlue); + swaps(&pRep->screenRed); + swaps(&pRep->screenGreen); + swaps(&pRep->screenBlue); + (void) WriteToClient(pClient, size, (char *) pRep); +} + +void +SAllocColorCellsReply(ClientPtr pClient, int size, xAllocColorCellsReply * pRep) +{ + swaps(&pRep->sequenceNumber); + swapl(&pRep->length); + swaps(&pRep->nPixels); + swaps(&pRep->nMasks); + (void) WriteToClient(pClient, size, (char *) pRep); +} + +void +SAllocColorPlanesReply(ClientPtr pClient, int size, + xAllocColorPlanesReply * pRep) +{ + swaps(&pRep->sequenceNumber); + swapl(&pRep->length); + swaps(&pRep->nPixels); + swapl(&pRep->redMask); + swapl(&pRep->greenMask); + swapl(&pRep->blueMask); + (void) WriteToClient(pClient, size, (char *) pRep); +} + +void +SwapRGB(xrgb * prgb) +{ + swaps(&prgb->red); + swaps(&prgb->green); + swaps(&prgb->blue); +} + +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) +{ + swaps(&pRep->sequenceNumber); + swapl(&pRep->length); + swaps(&pRep->nColors); + (void) WriteToClient(pClient, size, (char *) pRep); +} + +void +SLookupColorReply(ClientPtr pClient, int size, xLookupColorReply * pRep) +{ + swaps(&pRep->sequenceNumber); + swaps(&pRep->exactRed); + swaps(&pRep->exactGreen); + swaps(&pRep->exactBlue); + swaps(&pRep->screenRed); + swaps(&pRep->screenGreen); + swaps(&pRep->screenBlue); + (void) WriteToClient(pClient, size, (char *) pRep); +} + +void +SQueryBestSizeReply(ClientPtr pClient, int size, xQueryBestSizeReply * pRep) +{ + swaps(&pRep->sequenceNumber); + swaps(&pRep->width); + swaps(&pRep->height); + (void) WriteToClient(pClient, size, (char *) pRep); +} + +void +SListExtensionsReply(ClientPtr pClient, int size, xListExtensionsReply * pRep) +{ + swaps(&pRep->sequenceNumber); + swapl(&pRep->length); + (void) WriteToClient(pClient, size, (char *) pRep); +} + +void +SGetKeyboardMappingReply(ClientPtr pClient, int size, + xGetKeyboardMappingReply * pRep) +{ + swaps(&pRep->sequenceNumber); + swapl(&pRep->length); + (void) WriteToClient(pClient, size, (char *) pRep); +} + +void +SGetPointerMappingReply(ClientPtr pClient, int size, + xGetPointerMappingReply * pRep) +{ + swaps(&pRep->sequenceNumber); + swapl(&pRep->length); + (void) WriteToClient(pClient, size, (char *) pRep); +} + +void +SGetModifierMappingReply(ClientPtr pClient, int size, + xGetModifierMappingReply * pRep) +{ + swaps(&pRep->sequenceNumber); + swapl(&pRep->length); + (void) WriteToClient(pClient, size, (char *) pRep); +} + +void +SGetKeyboardControlReply(ClientPtr pClient, int size, + xGetKeyboardControlReply * pRep) +{ + swaps(&pRep->sequenceNumber); + swapl(&pRep->length); + swapl(&pRep->ledMask); + swaps(&pRep->bellPitch); + swaps(&pRep->bellDuration); + (void) WriteToClient(pClient, size, (char *) pRep); +} + +void +SGetPointerControlReply(ClientPtr pClient, int size, + xGetPointerControlReply * pRep) +{ + swaps(&pRep->sequenceNumber); + swaps(&pRep->accelNumerator); + swaps(&pRep->accelDenominator); + swaps(&pRep->threshold); + (void) WriteToClient(pClient, size, (char *) pRep); +} + +void +SGetScreenSaverReply(ClientPtr pClient, int size, xGetScreenSaverReply * pRep) +{ + swaps(&pRep->sequenceNumber); + swaps(&pRep->timeout); + swaps(&pRep->interval); + (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; + + swaps(&host->length); + bufT += sizeof(xHostEntry) + (((len + 3) >> 2) << 2); + } + (void) WriteToClient(pClient, size, buf); +} + +void +SListHostsReply(ClientPtr pClient, int size, xListHostsReply * pRep) +{ + swaps(&pRep->sequenceNumber); + swapl(&pRep->length); + swaps(&pRep->nHosts); + (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/dix/swapreq.c b/dix/swapreq.c new file mode 100644 index 0000000..470b349 --- /dev/null +++ b/dix/swapreq.c @@ -0,0 +1,1084 @@ +/************************************************************ + +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 +#endif + +#include +#include +#include +#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) +{ + + while (count >= 8) { + swapl(list + 0); + swapl(list + 1); + swapl(list + 2); + swapl(list + 3); + swapl(list + 4); + swapl(list + 5); + swapl(list + 6); + swapl(list + 7); + list += 8; + count -= 8; + } + if (count != 0) { + do { + swapl(list); + list++; + } while (--count != 0); + } +} + +/* Byte swap a list of shorts */ +_X_EXPORT void +SwapShorts(register short *list, register unsigned long count) +{ + + while (count >= 16) { + swaps(list + 0); + swaps(list + 1); + swaps(list + 2); + swaps(list + 3); + swaps(list + 4); + swaps(list + 5); + swaps(list + 6); + swaps(list + 7); + swaps(list + 8); + swaps(list + 9); + swaps(list + 10); + swaps(list + 11); + swaps(list + 12); + swaps(list + 13); + swaps(list + 14); + swaps(list + 15); + list += 16; + count -= 16; + } + if (count != 0) { + do { + swaps(list); + 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) +{ + + REQUEST(xReq); + swaps(&stuff->length); + 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) +{ + + REQUEST(xResourceReq); + swaps(&stuff->length); + REQUEST_AT_LEAST_SIZE(xResourceReq); /* not EXACT */ + swapl(&stuff->id); + return (*ProcVector[stuff->reqType]) (client); +} + +int +SProcCreateWindow(register ClientPtr client) +{ + + REQUEST(xCreateWindowReq); + swaps(&stuff->length); + REQUEST_AT_LEAST_SIZE(xCreateWindowReq); + swapl(&stuff->wid); + swapl(&stuff->parent); + swaps(&stuff->x); + swaps(&stuff->y); + swaps(&stuff->width); + swaps(&stuff->height); + swaps(&stuff->borderWidth); + swaps(&stuff->class); + swapl(&stuff->visual); + swapl(&stuff->mask); + SwapRestL(stuff); + return ((*ProcVector[X_CreateWindow]) (client)); +} + +int +SProcChangeWindowAttributes(register ClientPtr client) +{ + + REQUEST(xChangeWindowAttributesReq); + swaps(&stuff->length); + REQUEST_AT_LEAST_SIZE(xChangeWindowAttributesReq); + swapl(&stuff->window); + swapl(&stuff->valueMask); + SwapRestL(stuff); + return ((*ProcVector[X_ChangeWindowAttributes]) (client)); +} + +int +SProcReparentWindow(register ClientPtr client) +{ + + REQUEST(xReparentWindowReq); + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xReparentWindowReq); + swapl(&stuff->window); + swapl(&stuff->parent); + swaps(&stuff->x); + swaps(&stuff->y); + return ((*ProcVector[X_ReparentWindow]) (client)); +} + +int +SProcConfigureWindow(register ClientPtr client) +{ + + REQUEST(xConfigureWindowReq); + swaps(&stuff->length); + REQUEST_AT_LEAST_SIZE(xConfigureWindowReq); + swapl(&stuff->window); + swaps(&stuff->mask); + SwapRestL(stuff); + return ((*ProcVector[X_ConfigureWindow]) (client)); + +} + +int +SProcInternAtom(register ClientPtr client) +{ + + REQUEST(xInternAtomReq); + swaps(&stuff->length); + REQUEST_AT_LEAST_SIZE(xInternAtomReq); + swaps(&stuff->nbytes); + return ((*ProcVector[X_InternAtom]) (client)); +} + +int +SProcChangeProperty(register ClientPtr client) +{ + + REQUEST(xChangePropertyReq); + swaps(&stuff->length); + REQUEST_AT_LEAST_SIZE(xChangePropertyReq); + swapl(&stuff->window); + swapl(&stuff->property); + swapl(&stuff->type); + swapl(&stuff->nUnits); + 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) +{ + + REQUEST(xDeletePropertyReq); + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xDeletePropertyReq); + swapl(&stuff->window); + swapl(&stuff->property); + return ((*ProcVector[X_DeleteProperty]) (client)); + +} + +int +SProcGetProperty(register ClientPtr client) +{ + + REQUEST(xGetPropertyReq); + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xGetPropertyReq); + swapl(&stuff->window); + swapl(&stuff->property); + swapl(&stuff->type); + swapl(&stuff->longOffset); + swapl(&stuff->longLength); + return ((*ProcVector[X_GetProperty]) (client)); +} + +int +SProcSetSelectionOwner(register ClientPtr client) +{ + + REQUEST(xSetSelectionOwnerReq); + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xSetSelectionOwnerReq); + swapl(&stuff->window); + swapl(&stuff->selection); + swapl(&stuff->time); + return ((*ProcVector[X_SetSelectionOwner]) (client)); +} + +int +SProcConvertSelection(register ClientPtr client) +{ + + REQUEST(xConvertSelectionReq); + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xConvertSelectionReq); + swapl(&stuff->requestor); + swapl(&stuff->selection); + swapl(&stuff->target); + swapl(&stuff->property); + swapl(&stuff->time); + return ((*ProcVector[X_ConvertSelection]) (client)); +} + +int +SProcSendEvent(register ClientPtr client) +{ + + xEvent eventT; + + EventSwapPtr proc; + + REQUEST(xSendEventReq); + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xSendEventReq); + swapl(&stuff->destination); + swapl(&stuff->eventMask); + + /* 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) +{ + + REQUEST(xGrabPointerReq); + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xGrabPointerReq); + swapl(&stuff->grabWindow); + swaps(&stuff->eventMask); + swapl(&stuff->confineTo); + swapl(&stuff->cursor); + swapl(&stuff->time); + return ((*ProcVector[X_GrabPointer]) (client)); +} + +int +SProcGrabButton(register ClientPtr client) +{ + + REQUEST(xGrabButtonReq); + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xGrabButtonReq); + swapl(&stuff->grabWindow); + swaps(&stuff->eventMask); + swapl(&stuff->confineTo); + swapl(&stuff->cursor); + swaps(&stuff->modifiers); + return ((*ProcVector[X_GrabButton]) (client)); +} + +int +SProcUngrabButton(register ClientPtr client) +{ + + REQUEST(xUngrabButtonReq); + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xUngrabButtonReq); + swapl(&stuff->grabWindow); + swaps(&stuff->modifiers); + return ((*ProcVector[X_UngrabButton]) (client)); +} + +int +SProcChangeActivePointerGrab(register ClientPtr client) +{ + + REQUEST(xChangeActivePointerGrabReq); + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xChangeActivePointerGrabReq); + swapl(&stuff->cursor); + swapl(&stuff->time); + swaps(&stuff->eventMask); + return ((*ProcVector[X_ChangeActivePointerGrab]) (client)); +} + +int +SProcGrabKeyboard(register ClientPtr client) +{ + + REQUEST(xGrabKeyboardReq); + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xGrabKeyboardReq); + swapl(&stuff->grabWindow); + swapl(&stuff->time); + return ((*ProcVector[X_GrabKeyboard]) (client)); +} + +int +SProcGrabKey(register ClientPtr client) +{ + + REQUEST(xGrabKeyReq); + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xGrabKeyReq); + swapl(&stuff->grabWindow); + swaps(&stuff->modifiers); + return ((*ProcVector[X_GrabKey]) (client)); +} + +int +SProcUngrabKey(register ClientPtr client) +{ + + REQUEST(xUngrabKeyReq); + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xUngrabKeyReq); + swapl(&stuff->grabWindow); + swaps(&stuff->modifiers); + return ((*ProcVector[X_UngrabKey]) (client)); +} + +int +SProcGetMotionEvents(register ClientPtr client) +{ + + REQUEST(xGetMotionEventsReq); + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xGetMotionEventsReq); + swapl(&stuff->window); + swapl(&stuff->start); + swapl(&stuff->stop); + return ((*ProcVector[X_GetMotionEvents]) (client)); +} + +int +SProcTranslateCoords(register ClientPtr client) +{ + + REQUEST(xTranslateCoordsReq); + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xTranslateCoordsReq); + swapl(&stuff->srcWid); + swapl(&stuff->dstWid); + swaps(&stuff->srcX); + swaps(&stuff->srcY); + return ((*ProcVector[X_TranslateCoords]) (client)); +} + +int +SProcWarpPointer(register ClientPtr client) +{ + + REQUEST(xWarpPointerReq); + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xWarpPointerReq); + swapl(&stuff->srcWid); + swapl(&stuff->dstWid); + swaps(&stuff->srcX); + swaps(&stuff->srcY); + swaps(&stuff->srcWidth); + swaps(&stuff->srcHeight); + swaps(&stuff->dstX); + swaps(&stuff->dstY); + return ((*ProcVector[X_WarpPointer]) (client)); +} + +int +SProcSetInputFocus(register ClientPtr client) +{ + + REQUEST(xSetInputFocusReq); + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xSetInputFocusReq); + swapl(&stuff->focus); + swapl(&stuff->time); + return ((*ProcVector[X_SetInputFocus]) (client)); +} + +int +SProcOpenFont(register ClientPtr client) +{ + + REQUEST(xOpenFontReq); + swaps(&stuff->length); + REQUEST_AT_LEAST_SIZE(xOpenFontReq); + swapl(&stuff->fid); + swaps(&stuff->nbytes); + return ((*ProcVector[X_OpenFont]) (client)); +} + +int +SProcListFonts(register ClientPtr client) +{ + + REQUEST(xListFontsReq); + swaps(&stuff->length); + REQUEST_AT_LEAST_SIZE(xListFontsReq); + swaps(&stuff->maxNames); + swaps(&stuff->nbytes); + return ((*ProcVector[X_ListFonts]) (client)); +} + +int +SProcListFontsWithInfo(register ClientPtr client) +{ + + REQUEST(xListFontsWithInfoReq); + swaps(&stuff->length); + REQUEST_AT_LEAST_SIZE(xListFontsWithInfoReq); + swaps(&stuff->maxNames); + swaps(&stuff->nbytes); + return ((*ProcVector[X_ListFontsWithInfo]) (client)); +} + +int +SProcSetFontPath(register ClientPtr client) +{ + + REQUEST(xSetFontPathReq); + swaps(&stuff->length); + REQUEST_AT_LEAST_SIZE(xSetFontPathReq); + swaps(&stuff->nFonts); + return ((*ProcVector[X_SetFontPath]) (client)); +} + +int +SProcCreatePixmap(register ClientPtr client) +{ + + REQUEST(xCreatePixmapReq); + + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xCreatePixmapReq); + swapl(&stuff->pid); + swapl(&stuff->drawable); + swaps(&stuff->width); + swaps(&stuff->height); + return ((*ProcVector[X_CreatePixmap]) (client)); +} + +int +SProcCreateGC(register ClientPtr client) +{ + + REQUEST(xCreateGCReq); + swaps(&stuff->length); + REQUEST_AT_LEAST_SIZE(xCreateGCReq); + swapl(&stuff->gc); + swapl(&stuff->drawable); + swapl(&stuff->mask); + SwapRestL(stuff); + return ((*ProcVector[X_CreateGC]) (client)); +} + +int +SProcChangeGC(register ClientPtr client) +{ + + REQUEST(xChangeGCReq); + swaps(&stuff->length); + REQUEST_AT_LEAST_SIZE(xChangeGCReq); + swapl(&stuff->gc); + swapl(&stuff->mask); + SwapRestL(stuff); + return ((*ProcVector[X_ChangeGC]) (client)); +} + +int +SProcCopyGC(register ClientPtr client) +{ + + REQUEST(xCopyGCReq); + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xCopyGCReq); + swapl(&stuff->srcGC); + swapl(&stuff->dstGC); + swapl(&stuff->mask); + return ((*ProcVector[X_CopyGC]) (client)); +} + +int +SProcSetDashes(register ClientPtr client) +{ + + REQUEST(xSetDashesReq); + swaps(&stuff->length); + REQUEST_AT_LEAST_SIZE(xSetDashesReq); + swapl(&stuff->gc); + swaps(&stuff->dashOffset); + swaps(&stuff->nDashes); + return ((*ProcVector[X_SetDashes]) (client)); + +} + +int +SProcSetClipRectangles(register ClientPtr client) +{ + + REQUEST(xSetClipRectanglesReq); + swaps(&stuff->length); + REQUEST_AT_LEAST_SIZE(xSetClipRectanglesReq); + swapl(&stuff->gc); + swaps(&stuff->xOrigin); + swaps(&stuff->yOrigin); + SwapRestS(stuff); + return ((*ProcVector[X_SetClipRectangles]) (client)); +} + +int +SProcClearToBackground(register ClientPtr client) +{ + + REQUEST(xClearAreaReq); + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xClearAreaReq); + swapl(&stuff->window); + swaps(&stuff->x); + swaps(&stuff->y); + swaps(&stuff->width); + swaps(&stuff->height); + return ((*ProcVector[X_ClearArea]) (client)); +} + +int +SProcCopyArea(register ClientPtr client) +{ + + REQUEST(xCopyAreaReq); + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xCopyAreaReq); + swapl(&stuff->srcDrawable); + swapl(&stuff->dstDrawable); + swapl(&stuff->gc); + swaps(&stuff->srcX); + swaps(&stuff->srcY); + swaps(&stuff->dstX); + swaps(&stuff->dstY); + swaps(&stuff->width); + swaps(&stuff->height); + return ((*ProcVector[X_CopyArea]) (client)); +} + +int +SProcCopyPlane(register ClientPtr client) +{ + + REQUEST(xCopyPlaneReq); + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xCopyPlaneReq); + swapl(&stuff->srcDrawable); + swapl(&stuff->dstDrawable); + swapl(&stuff->gc); + swaps(&stuff->srcX); + swaps(&stuff->srcY); + swaps(&stuff->dstX); + swaps(&stuff->dstY); + swaps(&stuff->width); + swaps(&stuff->height); + swapl(&stuff->bitPlane); + 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) +{ + + REQUEST(xPolyPointReq); + swaps(&stuff->length); + REQUEST_AT_LEAST_SIZE(xPolyPointReq); + swapl(&stuff->drawable); + swapl(&stuff->gc); + 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) +{ + + REQUEST(xFillPolyReq); + swaps(&stuff->length); + REQUEST_AT_LEAST_SIZE(xFillPolyReq); + swapl(&stuff->drawable); + swapl(&stuff->gc); + SwapRestS(stuff); + return ((*ProcVector[X_FillPoly]) (client)); +} + +int +SProcPutImage(register ClientPtr client) +{ + + REQUEST(xPutImageReq); + swaps(&stuff->length); + REQUEST_AT_LEAST_SIZE(xPutImageReq); + swapl(&stuff->drawable); + swapl(&stuff->gc); + swaps(&stuff->width); + swaps(&stuff->height); + swaps(&stuff->dstX); + swaps(&stuff->dstY); + /* Image should already be swapped */ + return ((*ProcVector[X_PutImage]) (client)); + +} + +int +SProcGetImage(register ClientPtr client) +{ + + REQUEST(xGetImageReq); + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xGetImageReq); + swapl(&stuff->drawable); + swaps(&stuff->x); + swaps(&stuff->y); + swaps(&stuff->width); + swaps(&stuff->height); + swapl(&stuff->planeMask); + return ((*ProcVector[X_GetImage]) (client)); +} + +/* ProcPolyText used for both PolyText8 and PolyText16 */ + +int +SProcPolyText(register ClientPtr client) +{ + + REQUEST(xPolyTextReq); + swaps(&stuff->length); + REQUEST_AT_LEAST_SIZE(xPolyTextReq); + swapl(&stuff->drawable); + swapl(&stuff->gc); + swaps(&stuff->x); + swaps(&stuff->y); + return ((*ProcVector[stuff->reqType]) (client)); +} + +/* ProcImageText used for both ImageText8 and ImageText16 */ + +int +SProcImageText(register ClientPtr client) +{ + + REQUEST(xImageTextReq); + swaps(&stuff->length); + REQUEST_AT_LEAST_SIZE(xImageTextReq); + swapl(&stuff->drawable); + swapl(&stuff->gc); + swaps(&stuff->x); + swaps(&stuff->y); + return ((*ProcVector[stuff->reqType]) (client)); +} + +int +SProcCreateColormap(register ClientPtr client) +{ + + REQUEST(xCreateColormapReq); + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xCreateColormapReq); + swapl(&stuff->mid); + swapl(&stuff->window); + swapl(&stuff->visual); + return ((*ProcVector[X_CreateColormap]) (client)); +} + +int +SProcCopyColormapAndFree(register ClientPtr client) +{ + + REQUEST(xCopyColormapAndFreeReq); + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xCopyColormapAndFreeReq); + swapl(&stuff->mid); + swapl(&stuff->srcCmap); + return ((*ProcVector[X_CopyColormapAndFree]) (client)); + +} + +int +SProcAllocColor(register ClientPtr client) +{ + + REQUEST(xAllocColorReq); + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xAllocColorReq); + swapl(&stuff->cmap); + swaps(&stuff->red); + swaps(&stuff->green); + swaps(&stuff->blue); + return ((*ProcVector[X_AllocColor]) (client)); +} + +int +SProcAllocNamedColor(register ClientPtr client) +{ + + REQUEST(xAllocNamedColorReq); + swaps(&stuff->length); + REQUEST_AT_LEAST_SIZE(xAllocNamedColorReq); + swapl(&stuff->cmap); + swaps(&stuff->nbytes); + return ((*ProcVector[X_AllocNamedColor]) (client)); +} + +int +SProcAllocColorCells(register ClientPtr client) +{ + + REQUEST(xAllocColorCellsReq); + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xAllocColorCellsReq); + swapl(&stuff->cmap); + swaps(&stuff->colors); + swaps(&stuff->planes); + return ((*ProcVector[X_AllocColorCells]) (client)); +} + +int +SProcAllocColorPlanes(register ClientPtr client) +{ + + REQUEST(xAllocColorPlanesReq); + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xAllocColorPlanesReq); + swapl(&stuff->cmap); + swaps(&stuff->colors); + swaps(&stuff->red); + swaps(&stuff->green); + swaps(&stuff->blue); + return ((*ProcVector[X_AllocColorPlanes]) (client)); +} + +int +SProcFreeColors(register ClientPtr client) +{ + + REQUEST(xFreeColorsReq); + swaps(&stuff->length); + REQUEST_AT_LEAST_SIZE(xFreeColorsReq); + swapl(&stuff->cmap); + swapl(&stuff->planeMask); + SwapRestL(stuff); + return ((*ProcVector[X_FreeColors]) (client)); + +} + +_X_EXPORT void +SwapColorItem(xColorItem * pItem) +{ + + swapl(&pItem->pixel); + swaps(&pItem->red); + swaps(&pItem->green); + swaps(&pItem->blue); +} + +int +SProcStoreColors(register ClientPtr client) +{ + + long count; + + xColorItem *pItem; + + REQUEST(xStoreColorsReq); + swaps(&stuff->length); + REQUEST_AT_LEAST_SIZE(xStoreColorsReq); + swapl(&stuff->cmap); + pItem = (xColorItem *) & stuff[1]; + for (count = LengthRestB(stuff) / sizeof(xColorItem); --count >= 0;) + SwapColorItem(pItem++); + return ((*ProcVector[X_StoreColors]) (client)); +} + +int +SProcStoreNamedColor(register ClientPtr client) +{ + + REQUEST(xStoreNamedColorReq); + swaps(&stuff->length); + REQUEST_AT_LEAST_SIZE(xStoreNamedColorReq); + swapl(&stuff->cmap); + swapl(&stuff->pixel); + swaps(&stuff->nbytes); + return ((*ProcVector[X_StoreNamedColor]) (client)); +} + +int +SProcQueryColors(register ClientPtr client) +{ + + REQUEST(xQueryColorsReq); + swaps(&stuff->length); + REQUEST_AT_LEAST_SIZE(xQueryColorsReq); + swapl(&stuff->cmap); + SwapRestL(stuff); + return ((*ProcVector[X_QueryColors]) (client)); +} + +int +SProcLookupColor(register ClientPtr client) +{ + + REQUEST(xLookupColorReq); + swaps(&stuff->length); + REQUEST_AT_LEAST_SIZE(xLookupColorReq); + swapl(&stuff->cmap); + swaps(&stuff->nbytes); + return ((*ProcVector[X_LookupColor]) (client)); +} + +int +SProcCreateCursor(register ClientPtr client) +{ + + REQUEST(xCreateCursorReq); + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xCreateCursorReq); + swapl(&stuff->cid); + swapl(&stuff->source); + swapl(&stuff->mask); + swaps(&stuff->foreRed); + swaps(&stuff->foreGreen); + swaps(&stuff->foreBlue); + swaps(&stuff->backRed); + swaps(&stuff->backGreen); + swaps(&stuff->backBlue); + swaps(&stuff->x); + swaps(&stuff->y); + return ((*ProcVector[X_CreateCursor]) (client)); +} + +int +SProcCreateGlyphCursor(register ClientPtr client) +{ + + REQUEST(xCreateGlyphCursorReq); + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xCreateGlyphCursorReq); + swapl(&stuff->cid); + swapl(&stuff->source); + swapl(&stuff->mask); + swaps(&stuff->sourceChar); + swaps(&stuff->maskChar); + swaps(&stuff->foreRed); + swaps(&stuff->foreGreen); + swaps(&stuff->foreBlue); + swaps(&stuff->backRed); + swaps(&stuff->backGreen); + swaps(&stuff->backBlue); + return ((*ProcVector[X_CreateGlyphCursor]) (client)); +} + +int +SProcRecolorCursor(register ClientPtr client) +{ + + REQUEST(xRecolorCursorReq); + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xRecolorCursorReq); + swapl(&stuff->cursor); + swaps(&stuff->foreRed); + swaps(&stuff->foreGreen); + swaps(&stuff->foreBlue); + swaps(&stuff->backRed); + swaps(&stuff->backGreen); + swaps(&stuff->backBlue); + return ((*ProcVector[X_RecolorCursor]) (client)); +} + +int +SProcQueryBestSize(register ClientPtr client) +{ + + REQUEST(xQueryBestSizeReq); + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xQueryBestSizeReq); + swapl(&stuff->drawable); + swaps(&stuff->width); + swaps(&stuff->height); + return ((*ProcVector[X_QueryBestSize]) (client)); + +} + +int +SProcQueryExtension(register ClientPtr client) +{ + + REQUEST(xQueryExtensionReq); + swaps(&stuff->length); + REQUEST_AT_LEAST_SIZE(xQueryExtensionReq); + swaps(&stuff->nbytes); + return ((*ProcVector[X_QueryExtension]) (client)); +} + +int +SProcChangeKeyboardMapping(register ClientPtr client) +{ + + REQUEST(xChangeKeyboardMappingReq); + swaps(&stuff->length); + REQUEST_AT_LEAST_SIZE(xChangeKeyboardMappingReq); + SwapRestL(stuff); + return ((*ProcVector[X_ChangeKeyboardMapping]) (client)); +} + +int +SProcChangeKeyboardControl(register ClientPtr client) +{ + + REQUEST(xChangeKeyboardControlReq); + swaps(&stuff->length); + REQUEST_AT_LEAST_SIZE(xChangeKeyboardControlReq); + swapl(&stuff->mask); + SwapRestL(stuff); + return ((*ProcVector[X_ChangeKeyboardControl]) (client)); +} + +int +SProcChangePointerControl(register ClientPtr client) +{ + + REQUEST(xChangePointerControlReq); + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xChangePointerControlReq); + swaps(&stuff->accelNum); + swaps(&stuff->accelDenum); + swaps(&stuff->threshold); + return ((*ProcVector[X_ChangePointerControl]) (client)); +} + +int +SProcSetScreenSaver(register ClientPtr client) +{ + + REQUEST(xSetScreenSaverReq); + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xSetScreenSaverReq); + swaps(&stuff->timeout); + swaps(&stuff->interval); + return ((*ProcVector[X_SetScreenSaver]) (client)); +} + +int +SProcChangeHosts(register ClientPtr client) +{ + + REQUEST(xChangeHostsReq); + swaps(&stuff->length); + REQUEST_AT_LEAST_SIZE(xChangeHostsReq); + swaps(&stuff->hostLength); + return ((*ProcVector[X_ChangeHosts]) (client)); + +} + +int +SProcRotateProperties(register ClientPtr client) +{ + + REQUEST(xRotatePropertiesReq); + swaps(&stuff->length); + REQUEST_AT_LEAST_SIZE(xRotatePropertiesReq); + swapl(&stuff->window); + swaps(&stuff->nAtoms); + swaps(&stuff->nPositions); + SwapRestL(stuff); + return ((*ProcVector[X_RotateProperties]) (client)); +} + +int +SProcNoOperation(register ClientPtr client) +{ + + REQUEST(xReq); + swaps(&stuff->length); + return ((*ProcVector[X_NoOperation]) (client)); +} + +void +SwapConnClientPrefix(xConnClientPrefix * pCCP) +{ + + swaps(&pCCP->majorVersion); + swaps(&pCCP->minorVersion); + swaps(&pCCP->nbytesAuthProto); + swaps(&pCCP->nbytesAuthString); +} diff --git a/dix/tables.c b/dix/tables.c new file mode 100644 index 0000000..3e22b65 --- /dev/null +++ b/dix/tables.c @@ -0,0 +1,985 @@ +/*********************************************************** + +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 +#endif + +#include +#include +#include "windowstr.h" +#include "extnsionst.h" +#include "dixstruct.h" +#include "dixevents.h" +#include "dispatch.h" +#include "swaprep.h" +#include "swapreq.h" + +int (* InitialVector[3]) ( + ClientPtr /* client */ + ) = +{ + 0, + ProcInitialConnection, + ProcEstablishConnection +}; + +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, + ProcBadRequest, /* 120 */ + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, /* 125 */ + ProcBadRequest, + ProcNoOperation, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest +}; + +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, */ + ProcBadRequest, /* 120 */ + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, /* 125 */ + ProcBadRequest, + SProcNoOperation, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest, + ProcBadRequest +}; + +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, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented, + NotImplemented +}; + + +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, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd, + ReplyNotSwappd +}; diff --git a/dix/window.c b/dix/window.c new file mode 100644 index 0000000..d327531 --- /dev/null +++ b/dix/window.c @@ -0,0 +1,3362 @@ +/* + +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. + +*/ + +#ifdef HAVE_DIX_CONFIG_H +#include +#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" +#include "dixevents.h" +#include "globals.h" + + +/****** + * Window stuff for server + * + * CreateRootWindow, CreateWindow, ChangeWindowAttributes, + * GetWindowAttributes, DeleteWindow, DestroySubWindows, + * HandleSaveSet, ReparentWindow, MapWindow, MapSubWindows, + * UnmapWindow, UnmapSubWindows, ConfigureWindow, CirculateWindow, + * + ******/ + +static const unsigned char _back_lsb[4] = { 0x88, 0x22, 0x44, 0x11 }; +static const unsigned char _back_msb[4] = { 0x11, 0x44, 0x22, 0x88 }; + +_X_EXPORT int screenIsSaved = SCREEN_SAVER_OFF; + +_X_EXPORT ScreenSaverStuffRec savedScreenInfo[MAXSCREENS]; + +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)) + +#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) +{ + int result; + + 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 */ +static const int defaultBackingStore = NotUseful; + +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 +} + +static void +MakeRootTile(WindowPtr pWin) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + + GCPtr pGC; + + unsigned char back[128]; + + int len = BitmapBytePad(sizeof(long)); + + const unsigned char *from; + unsigned char *to; + + 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; + + char *ptr; + + DevUnion *ppriv; + + unsigned *sizes; + + unsigned size; + + int i; + + pWin = malloc(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 = malloc(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; + pWin->optional->boundingShape = NULL; + pWin->optional->clipShape = NULL; + pWin->optional->inputShape = NULL; + 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; + + BoxRec *boxptr = &box; + + REGION_INIT(&pWin->clipList, boxptr, 1); + REGION_INIT(&pWin->winSize, boxptr, 1); + REGION_INIT(&pWin->borderSize, boxptr, 1); + REGION_INIT(&pWin->borderClip, boxptr, 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; + + 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); + + + 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) +{ + BoxRec box; + + box = *(REGION_EXTENTS(&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(Rgn, &box); + REGION_INTERSECT(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) +{ + WindowPtr pWin; + + WindowPtr pHead; + + ScreenPtr pScreen; + + xEvent event; + + int idepth, ivisual; + + Bool fOK; + + DepthPtr pDepth; + + PixmapFormatRec *format; + + 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) { + 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)) { + free(pWin); + *error = BadAlloc; + return NullWindow; + } + pWin->optional->visual = visual; + pWin->optional->colormap = None; + } + + pWin->borderWidth = bw; + 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(&pWin->clipList); + REGION_NULL(&pWin->borderClip); + REGION_NULL(&pWin->winSize); + REGION_NULL(&pWin->borderSize); + + + 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) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + + DeleteWindowFromAnySaveSet(pWin); + DeleteWindowFromAnySelections(pWin); + DeleteWindowFromAnyEvents(pWin, TRUE); + REGION_UNINIT(&pWin->clipList); + REGION_UNINIT(&pWin->winSize); + REGION_UNINIT(&pWin->borderClip); + REGION_UNINIT(&pWin->borderSize); + if (wBoundingShape(pWin)) + REGION_DESTROY(wBoundingShape(pWin)); + if (wClipShape(pWin)) + REGION_DESTROY(wClipShape(pWin)); + if (wInputShape(pWin)) + REGION_DESTROY(wInputShape(pWin)); + 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) +{ + 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; + pChild->viewable = FALSE; + if (pChild->realized) { + pChild->realized = FALSE; + (*UnrealizeWindow) (pChild); + } + FreeWindowResources(pChild); + free(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) +{ + WindowPtr pParent; + + 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; + } + free(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) +{ + Mask index2; + + XID *pVlist; + + PixmapPtr pPixmap; + + Pixmap pixID; + + CursorPtr pCursor, pOldCursor; + + Cursor cursorID; + + WindowPtr pChild; + + Colormap cmap; + + ColormapPtr pCmap; + + xEvent xE; + + int result; + + ScreenPtr pScreen; + + Mask vmaskCopy = 0; + + Mask tmask; + + unsigned int val; + + int error; + + Bool checkOptional = FALSE; + + Bool borderRelative = FALSE; + + 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) { + if (pWin->backgroundState == BackgroundPixmap) + (*pScreen->DestroyPixmap) (pWin->background.pixmap); + if (!pWin->parent) + MakeRootTile(pWin); + else + pWin->backgroundState = None; + } + 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; + } + pWin->saveUnder = val; + 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) { + 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(&exposed); + REGION_SUBTRACT(&exposed, &pWin->borderClip, &pWin->winSize); + (*pWin->drawable.pScreen->PaintWindowBorder) (pWin, &exposed, + PW_BORDER); + REGION_UNINIT(&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) +{ + 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); + } + + + return (pFirstChange); +} + +_X_EXPORT void +SetWinSize(register WindowPtr pWin) +{ + ClippedRegionFromBox(pWin->parent, &pWin->winSize, + pWin->drawable.x, pWin->drawable.y, + (int) pWin->drawable.width, + (int) pWin->drawable.height); + if (wBoundingShape(pWin) || wClipShape(pWin)) { + REGION_TRANSLATE(&pWin->winSize, -pWin->drawable.x, + -pWin->drawable.y); + if (wBoundingShape(pWin)) + REGION_INTERSECT(&pWin->winSize, &pWin->winSize, + wBoundingShape(pWin)); + if (wClipShape(pWin)) + REGION_INTERSECT(&pWin->winSize, &pWin->winSize, + wClipShape(pWin)); + REGION_TRANSLATE(&pWin->winSize, pWin->drawable.x, + pWin->drawable.y); + } +} + +_X_EXPORT void +SetBorderSize(register WindowPtr pWin) +{ + int bw; + + if (HasBorder(pWin)) { + bw = wBorderWidth(pWin); + 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))); + if (wBoundingShape(pWin)) { + REGION_TRANSLATE(&pWin->borderSize, -pWin->drawable.x, + -pWin->drawable.y); + REGION_INTERSECT(&pWin->borderSize, &pWin->borderSize, + wBoundingShape(pWin)); + REGION_TRANSLATE(&pWin->borderSize, pWin->drawable.x, + pWin->drawable.y); + REGION_UNION(&pWin->borderSize, &pWin->borderSize, + &pWin->winSize); + } + } + else { + REGION_COPY(&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) +{ + ScreenPtr pScreen; + + 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) +{ + 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); +} + +#define IS_SHAPED(pWin) (wBoundingShape (pWin) != (RegionPtr) NULL) + +static RegionPtr +MakeBoundingRegion(register WindowPtr pWin, BoxPtr pBox) +{ + RegionPtr pRgn; + + pRgn = REGION_CREATE(pBox, 1); + if (wBoundingShape(pWin)) { + REGION_TRANSLATE(pRgn, -pWin->origin.x, -pWin->origin.y); + REGION_INTERSECT(pRgn, pRgn, wBoundingShape(pWin)); + REGION_TRANSLATE(pRgn, pWin->origin.x, pWin->origin.y); + } + return pRgn; +} + +static Bool +ShapeOverlap(WindowPtr pWin, BoxPtr pWinBox, WindowPtr pSib, BoxPtr pSibBox) +{ + RegionPtr pWinRgn, pSibRgn; + + Bool ret; + + if (!IS_SHAPED(pWin) && !IS_SHAPED(pSib)) + return TRUE; + pWinRgn = MakeBoundingRegion(pWin, pWinBox); + pSibRgn = MakeBoundingRegion(pSib, pSibBox); + REGION_INTERSECT(pWinRgn, pWinRgn, pSibRgn); + ret = REGION_NOTEMPTY(pWinRgn); + REGION_DESTROY(pWinRgn); + REGION_DESTROY(pSibRgn); + return ret; +} + +static Bool +AnyWindowOverlapsMe(WindowPtr pWin, WindowPtr pHead, register BoxPtr box) +{ + WindowPtr pSib; + + BoxRec sboxrec; + + BoxPtr sbox; + + for (pSib = pWin->prevSib; pSib != pHead; pSib = pSib->prevSib) { + if (pSib->mapped) { + sbox = WindowExtents(pSib, &sboxrec); + if (BOXES_OVERLAP(sbox, box) + && ShapeOverlap(pWin, box, pSib, sbox) + ) + return (TRUE); + } + } + return (FALSE); +} + +static Bool +IOverlapAnyWindow(WindowPtr pWin, register BoxPtr box) +{ + WindowPtr pSib; + + BoxRec sboxrec; + + BoxPtr sbox; + + for (pSib = pWin->nextSib; pSib; pSib = pSib->nextSib) { + if (pSib->mapped) { + sbox = WindowExtents(pSib, &sboxrec); + if (BOXES_OVERLAP(sbox, box) + && ShapeOverlap(pWin, box, pSib, sbox) + ) + 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; + + 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; + 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(&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(&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(&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; + + 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; + if (anyMarked) { + (*pScreen->ValidateTree) (pLayerWin->parent, pFirstChange, kind); + (*pScreen->HandleExposures) (pLayerWin->parent); + } + 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 + WindowPtr pSib = NullWindow; + + WindowPtr pParent = pWin->parent; + + Window sibwid = 0; + + Mask index2, tmask; + + XID *pVlist; + + short x, y, beforeX, beforeY; + + unsigned short w = pWin->drawable.width, + h = pWin->drawable.height, bw = pWin->borderWidth; + int action, smode = Above; + + 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; + + + if ((!pWin->overrideRedirect) && (RedirectSend(pParent) + )) { + 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; + event.u.configureRequest.width = w; + event.u.configureRequest.height = h; + event.u.configureRequest.borderWidth = bw; + event.u.configureRequest.valueMask = mask; + 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) { + /* See above for why we always reorder in rootless mode. */ + if (pWin->nextSib != pSib) + 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; + 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) +{ + 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); + + 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; + 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) +{ + WindowPtr pChild; + + RealizeWindowProcPtr Realize; + + Realize = pWin->drawable.pScreen->RealizeWindow; + pChild = pWin; + while (1) { + if (pChild->mapped) { + pChild->realized = TRUE; + 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) +{ + ScreenPtr pScreen; + + WindowPtr pParent; + + WindowPtr pLayerWin; + + if (pWin->mapped) + return (Success); + + + pScreen = pWin->drawable.pScreen; + if ((pParent = pWin->parent)) { + xEvent event; + + Bool anyMarked; + + + if ((!pWin->overrideRedirect) && (RedirectSend(pParent) + )) { + 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) + 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); + if (anyMarked) { + (*pScreen->ValidateTree) (pLayerWin->parent, pLayerWin, VTMap); + (*pScreen->HandleExposures) (pLayerWin->parent); + } + 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(&temp); + REGION_COPY(&temp, &pWin->clipList); + (*pScreen->WindowExposures) (pWin, &temp, NullRegion); + REGION_UNINIT(&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) +{ + WindowPtr pWin; + + WindowPtr pFirstMapped = NullWindow; + + ScreenPtr pScreen; + + Mask parentRedirect; + + Mask parentNotify; + + xEvent event; + + Bool anyMarked; + + 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); + } + } + } + } + + if (pFirstMapped) { + pLayerWin = (*pScreen->GetLayerWindow) (pParent); + if (pLayerWin->parent != pParent) { + anyMarked |= (*pScreen->MarkOverlappedWindows) (pLayerWin, + pLayerWin, + (WindowPtr *) NULL); + pFirstMapped = pLayerWin; + } + if (anyMarked) { + (*pScreen->ValidateTree) (pLayerWin->parent, pFirstMapped, VTMap); + (*pScreen->HandleExposures) (pLayerWin->parent); + } + if (anyMarked && pScreen->PostValidateTree) + (*pScreen->PostValidateTree) (pLayerWin->parent, pFirstMapped, + VTMap); + WindowsRestructured(); + } +} + +static void +UnrealizeTree(WindowPtr pWin, Bool fromConfigure) +{ + 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; + (*Unrealize) (pChild); + DeleteWindowFromAnyEvents(pChild, FALSE); + if (pChild->viewable) { + pChild->viewable = FALSE; + (*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) +{ + 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); + } + 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) +{ + 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) { + } + } + } + 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); + } + if (anyMarked && pScreen->PostValidateTree) + (*pScreen->PostValidateTree) (pLayerWin->parent, pHead, VTUnmap); + } + if (wasRealized) + WindowsRestructured(); +} + +void +HandleSaveSet(register ClientPtr client) +{ + WindowPtr pParent, pWin; + + int j; + + for (j = 0; j < client->numSaved; j++) { + pWin = SaveSetWindow(client->saveSet[j]); + if (SaveSetToRoot(client->saveSet[j])) + pParent = WindowTable[pWin->drawable.pScreen->myNum]; + else + { + 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; + } + if (SaveSetRemap(client->saveSet[j])) + MapWindow(pWin, client); + } + } + free(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->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->borderClip, x, y, &box) + && (!wInputShape(pWin) || + POINT_IN_REGION( + wInputShape(pWin), + x - pWin->drawable.x, y - pWin->drawable.y, &box))) + return (TRUE); + return (FALSE); +} + +_X_EXPORT RegionPtr +NotClippedByChildren(register WindowPtr pWin) +{ + RegionPtr pReg; + + pReg = REGION_CREATE(NullBox, 1); + if (pWin->parent || + screenIsSaved != SCREEN_SAVER_ON || + !HasSaverWindow(pWin->drawable.pScreen->myNum)) { + REGION_INTERSECT(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 + + 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 = malloc(BitmapBytePad(32) * 16); + mskbits = malloc(BitmapBytePad(32) * 16); + if (!srcbits || !mskbits) { + free(srcbits); + free(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 { + free(srcbits); + free(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) +{ + WindowOptPtr optional; + + 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; + if (optional->boundingShape != NULL) + return; + if (optional->clipShape != NULL) + return; + if (optional->inputShape != NULL) + return; + 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) +{ + WindowOptPtr optional; + + WindowOptPtr parentOptional; + + if (pWin->optional) + return TRUE; + optional = malloc(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; + optional->boundingShape = NULL; + optional->clipShape = NULL; + optional->inputShape = NULL; + 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; + free(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/fb/Makefile.am b/fb/Makefile.am new file mode 100644 index 0000000..2d6490d --- /dev/null +++ b/fb/Makefile.am @@ -0,0 +1,45 @@ +noinst_LTLIBRARIES = libfb.la + +AM_CFLAGS = $(DIX_CFLAGS) + +libfb_la_SOURCES = \ + fb.h \ + fb24_32.c \ + fb24_32.h \ + fballpriv.c \ + fbarc.c \ + fbbits.c \ + fbbits.h \ + fbblt.c \ + fbbltone.c \ + fbcompose.c \ + fbcopy.c \ + fbfill.c \ + fbfillrect.c \ + fbfillsp.c \ + fbgc.c \ + fbgetsp.c \ + fbglyph.c \ + fbimage.c \ + fbline.c \ + fboverlay.c \ + fboverlay.h \ + fbpict.c \ + fbpict.h \ + fbpixmap.c \ + fbpoint.c \ + fbpush.c \ + fbrop.h \ + fbscreen.c \ + fbseg.c \ + fbsetsp.c \ + fbsolid.c \ + fbstipple.c \ + fbtile.c \ + fbtrap.c \ + fbutil.c \ + fbwindow.c \ + fbedge.c \ + fbedgeimp.h + +EXTRA_DIST = fbcmap.c diff --git a/fb/fb.h b/fb/fb.h new file mode 100644 index 0000000..a4ab5bf --- /dev/null +++ b/fb/fb.h @@ -0,0 +1,1565 @@ +/* + * + * Copyright © 1998 Keith Packard + * + * 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, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _FB_H_ +#define _FB_H_ + +#include +#include "scrnintstr.h" +#include "pixmap.h" +#include "pixmapstr.h" +#include "region.h" +#include "gcstruct.h" +#include "colormap.h" +#include "miscstruct.h" +#include "servermd.h" +#include "windowstr.h" +#include "mi.h" +#include "migc.h" +#include "picturestr.h" + +/* + * This single define controls the basic size of data manipulated + * by this software; it must be log2(sizeof (FbBits) * 8) + */ + +#ifndef FB_SHIFT +#define FB_SHIFT LOG2_BITMAP_PAD +#endif + +#if FB_SHIFT < LOG2_BITMAP_PAD +error FB_SHIFT must be >= LOG2_BITMAP_PAD +#endif +#define FB_UNIT (1 << FB_SHIFT) +#define FB_HALFUNIT (1 << (FB_SHIFT-1)) +#define FB_MASK (FB_UNIT - 1) +#define FB_ALLONES ((FbBits) -1) +#if GLYPHPADBYTES != 4 +#error "GLYPHPADBYTES must be 4" +#endif + +#define FB_STIP_SHIFT LOG2_BITMAP_PAD +#define FB_STIP_UNIT (1 << FB_STIP_SHIFT) +#define FB_STIP_MASK (FB_STIP_UNIT - 1) +#define FB_STIP_ALLONES ((FbStip) -1) +#define FB_STIP_ODDSTRIDE(s) (((s) & (FB_MASK >> FB_STIP_SHIFT)) != 0) +#define FB_STIP_ODDPTR(p) ((((long) (p)) & (FB_MASK >> 3)) != 0) +#define FbStipStrideToBitsStride(s) (((s) >> (FB_SHIFT - FB_STIP_SHIFT))) +#define FbBitsStrideToStipStride(s) (((s) << (FB_SHIFT - FB_STIP_SHIFT))) +#define FbFullMask(n) ((n) == FB_UNIT ? FB_ALLONES : ((((FbBits) 1) << n) - 1)) +#if FB_SHIFT == 6 +# if defined(__alpha__) || defined(__alpha) || \ + defined(ia64) || defined(__ia64__) || \ + defined(__sparc64__) || defined(_LP64) || \ + defined(__s390x__) || \ + defined(amd64) || defined (__amd64__) || \ + defined (__powerpc64__) || \ + (defined(sgi) && (_MIPS_SZLONG == 64)) +typedef unsigned long FbBits; +# else +typedef unsigned long long FbBits; +# endif +#endif + +#if FB_SHIFT == 5 +typedef CARD32 FbBits; +#endif + +#if FB_SHIFT == 4 +typedef CARD16 FbBits; +#endif + +#if LOG2_BITMAP_PAD == FB_SHIFT +typedef FbBits FbStip; +#else +#if LOG2_BITMAP_PAD == 5 +typedef CARD32 FbStip; +#endif +#endif + +typedef int FbStride; + +#ifdef FB_DEBUG +extern _X_EXPORT void fbValidateDrawable(DrawablePtr d); +extern _X_EXPORT void fbInitializeDrawable(DrawablePtr d); +extern _X_EXPORT void fbSetBits(FbStip * bits, int stride, FbStip data); + +#define FB_HEAD_BITS (FbStip) (0xbaadf00d) +#define FB_TAIL_BITS (FbStip) (0xbaddf0ad) +#else +#define fbValidateDrawable(d) +#define fdInitializeDrawable(d) +#endif + +#include "fbrop.h" + +#if BITMAP_BIT_ORDER == LSBFirst +#define FbScrLeft(x,n) ((x) >> (n)) +#define FbScrRight(x,n) ((x) << (n)) +/* #define FbLeftBits(x,n) ((x) & ((((FbBits) 1) << (n)) - 1)) */ +#define FbLeftStipBits(x,n) ((x) & ((((FbStip) 1) << (n)) - 1)) +#define FbStipMoveLsb(x,s,n) (FbStipRight (x,(s)-(n))) +#define FbPatternOffsetBits 0 +#else +#define FbScrLeft(x,n) ((x) << (n)) +#define FbScrRight(x,n) ((x) >> (n)) +/* #define FbLeftBits(x,n) ((x) >> (FB_UNIT - (n))) */ +#define FbLeftStipBits(x,n) ((x) >> (FB_STIP_UNIT - (n))) +#define FbStipMoveLsb(x,s,n) (x) +#define FbPatternOffsetBits (sizeof (FbBits) - 1) +#endif + +#include "micoord.h" + +#define FbStipLeft(x,n) FbScrLeft(x,n) +#define FbStipRight(x,n) FbScrRight(x,n) + +#define FbRotLeft(x,n) FbScrLeft(x,n) | (n ? FbScrRight(x,FB_UNIT-n) : 0) +#define FbRotRight(x,n) FbScrRight(x,n) | (n ? FbScrLeft(x,FB_UNIT-n) : 0) + +#define FbRotStipLeft(x,n) FbStipLeft(x,n) | (n ? FbStipRight(x,FB_STIP_UNIT-n) : 0) +#define FbRotStipRight(x,n) FbStipRight(x,n) | (n ? FbStipLeft(x,FB_STIP_UNIT-n) : 0) + +#define FbLeftMask(x) ( ((x) & FB_MASK) ? \ + FbScrRight(FB_ALLONES,(x) & FB_MASK) : 0) +#define FbRightMask(x) ( ((FB_UNIT - (x)) & FB_MASK) ? \ + FbScrLeft(FB_ALLONES,(FB_UNIT - (x)) & FB_MASK) : 0) + +#define FbLeftStipMask(x) ( ((x) & FB_STIP_MASK) ? \ + FbStipRight(FB_STIP_ALLONES,(x) & FB_STIP_MASK) : 0) +#define FbRightStipMask(x) ( ((FB_STIP_UNIT - (x)) & FB_STIP_MASK) ? \ + FbScrLeft(FB_STIP_ALLONES,(FB_STIP_UNIT - (x)) & FB_STIP_MASK) : 0) + +#define FbBitsMask(x,w) (FbScrRight(FB_ALLONES,(x) & FB_MASK) & \ + FbScrLeft(FB_ALLONES,(FB_UNIT - ((x) + (w))) & FB_MASK)) + +#define FbStipMask(x,w) (FbStipRight(FB_STIP_ALLONES,(x) & FB_STIP_MASK) & \ + FbStipLeft(FB_STIP_ALLONES,(FB_STIP_UNIT - ((x)+(w))) & FB_STIP_MASK)) + +#define FbMaskBits(x,w,l,n,r) { \ + n = (w); \ + r = FbRightMask((x)+n); \ + l = FbLeftMask(x); \ + if (l) { \ + n -= FB_UNIT - ((x) & FB_MASK); \ + if (n < 0) { \ + n = 0; \ + l &= r; \ + r = 0; \ + } \ + } \ + n >>= FB_SHIFT; \ +} + + +#define FbByteMaskInvalid 0x10 + +#define FbPatternOffset(o,t) ((o) ^ (FbPatternOffsetBits & ~(sizeof (t) - 1))) + +#define FbPtrOffset(p,o,t) ((t *) ((CARD8 *) (p) + (o))) +#define FbSelectPatternPart(xor,o,t) ((xor) >> (FbPatternOffset (o,t) << 3)) +#define FbStorePart(dst,off,t,xor) (*FbPtrOffset(dst,off,t) = \ + FbSelectPart(xor,off,t)) +#ifndef FbSelectPart +#define FbSelectPart(x,o,t) FbSelectPatternPart(x,o,t) +#endif + +#define FbMaskBitsBytes(x,w,copy,l,lb,n,r,rb) { \ + n = (w); \ + lb = 0; \ + rb = 0; \ + r = FbRightMask((x)+n); \ + if (r) { \ + /* compute right byte length */ \ + if ((copy) && (((x) + n) & 7) == 0) { \ + rb = (((x) + n) & FB_MASK) >> 3; \ + } else { \ + rb = FbByteMaskInvalid; \ + } \ + } \ + l = FbLeftMask(x); \ + if (l) { \ + /* compute left byte length */ \ + if ((copy) && ((x) & 7) == 0) { \ + lb = ((x) & FB_MASK) >> 3; \ + } else { \ + lb = FbByteMaskInvalid; \ + } \ + /* subtract out the portion painted by leftMask */ \ + n -= FB_UNIT - ((x) & FB_MASK); \ + if (n < 0) { \ + if (lb != FbByteMaskInvalid) { \ + if (rb == FbByteMaskInvalid) { \ + lb = FbByteMaskInvalid; \ + } else if (rb) { \ + lb |= (rb - lb) << (FB_SHIFT - 3); \ + rb = 0; \ + } \ + } \ + n = 0; \ + l &= r; \ + r = 0; \ + }\ + } \ + n >>= FB_SHIFT; \ +} + +#if FB_SHIFT == 6 +#define FbDoLeftMaskByteRRop6Cases(dst,xor) \ + case (sizeof (FbBits) - 7) | (1 << (FB_SHIFT - 3)): \ + FbStorePart(dst,sizeof (FbBits) - 7,CARD8,xor); \ + break; \ + case (sizeof (FbBits) - 7) | (2 << (FB_SHIFT - 3)): \ + FbStorePart(dst,sizeof (FbBits) - 7,CARD8,xor); \ + FbStorePart(dst,sizeof (FbBits) - 6,CARD8,xor); \ + break; \ + case (sizeof (FbBits) - 7) | (3 << (FB_SHIFT - 3)): \ + FbStorePart(dst,sizeof (FbBits) - 7,CARD8,xor); \ + FbStorePart(dst,sizeof (FbBits) - 6,CARD16,xor); \ + break; \ + case (sizeof (FbBits) - 7) | (4 << (FB_SHIFT - 3)): \ + FbStorePart(dst,sizeof (FbBits) - 7,CARD8,xor); \ + FbStorePart(dst,sizeof (FbBits) - 6,CARD16,xor); \ + FbStorePart(dst,sizeof (FbBits) - 4,CARD8,xor); \ + break; \ + case (sizeof (FbBits) - 7) | (5 << (FB_SHIFT - 3)): \ + FbStorePart(dst,sizeof (FbBits) - 7,CARD8,xor); \ + FbStorePart(dst,sizeof (FbBits) - 6,CARD16,xor); \ + FbStorePart(dst,sizeof (FbBits) - 4,CARD16,xor); \ + break; \ + case (sizeof (FbBits) - 7) | (6 << (FB_SHIFT - 3)): \ + FbStorePart(dst,sizeof (FbBits) - 7,CARD8,xor); \ + FbStorePart(dst,sizeof (FbBits) - 6,CARD16,xor); \ + FbStorePart(dst,sizeof (FbBits) - 4,CARD16,xor); \ + FbStorePart(dst,sizeof (FbBits) - 2,CARD8,xor); \ + break; \ + case (sizeof (FbBits) - 7): \ + FbStorePart(dst,sizeof (FbBits) - 7,CARD8,xor); \ + FbStorePart(dst,sizeof (FbBits) - 6,CARD16,xor); \ + FbStorePart(dst,sizeof (FbBits) - 4,CARD32,xor); \ + break; \ + case (sizeof (FbBits) - 6) | (1 << (FB_SHIFT - 3)): \ + FbStorePart(dst,sizeof (FbBits) - 6,CARD8,xor); \ + break; \ + case (sizeof (FbBits) - 6) | (2 << (FB_SHIFT - 3)): \ + FbStorePart(dst,sizeof (FbBits) - 6,CARD16,xor); \ + break; \ + case (sizeof (FbBits) - 6) | (3 << (FB_SHIFT - 3)): \ + FbStorePart(dst,sizeof (FbBits) - 6,CARD16,xor); \ + FbStorePart(dst,sizeof (FbBits) - 4,CARD8,xor); \ + break; \ + case (sizeof (FbBits) - 6) | (4 << (FB_SHIFT - 3)): \ + FbStorePart(dst,sizeof (FbBits) - 6,CARD16,xor); \ + FbStorePart(dst,sizeof (FbBits) - 4,CARD16,xor); \ + break; \ + case (sizeof (FbBits) - 6) | (5 << (FB_SHIFT - 3)): \ + FbStorePart(dst,sizeof (FbBits) - 6,CARD16,xor); \ + FbStorePart(dst,sizeof (FbBits) - 4,CARD16,xor); \ + FbStorePart(dst,sizeof (FbBits) - 2,CARD8,xor); \ + break; \ + case (sizeof (FbBits) - 6): \ + FbStorePart(dst,sizeof (FbBits) - 6,CARD16,xor); \ + FbStorePart(dst,sizeof (FbBits) - 4,CARD32,xor); \ + break; \ + case (sizeof (FbBits) - 5) | (1 << (FB_SHIFT - 3)): \ + FbStorePart(dst,sizeof (FbBits) - 5,CARD8,xor); \ + break; \ + case (sizeof (FbBits) - 5) | (2 << (FB_SHIFT - 3)): \ + FbStorePart(dst,sizeof (FbBits) - 5,CARD8,xor); \ + FbStorePart(dst,sizeof (FbBits) - 4,CARD8,xor); \ + break; \ + case (sizeof (FbBits) - 5) | (3 << (FB_SHIFT - 3)): \ + FbStorePart(dst,sizeof (FbBits) - 5,CARD8,xor); \ + FbStorePart(dst,sizeof (FbBits) - 4,CARD16,xor); \ + break; \ + case (sizeof (FbBits) - 5) | (4 << (FB_SHIFT - 3)): \ + FbStorePart(dst,sizeof (FbBits) - 5,CARD8,xor); \ + FbStorePart(dst,sizeof (FbBits) - 4,CARD16,xor); \ + FbStorePart(dst,sizeof (FbBits) - 2,CARD8,xor); \ + break; \ + case (sizeof (FbBits) - 5): \ + FbStorePart(dst,sizeof (FbBits) - 5,CARD8,xor); \ + FbStorePart(dst,sizeof (FbBits) - 4,CARD32,xor); \ + break; \ + case (sizeof (FbBits) - 4) | (1 << (FB_SHIFT - 3)): \ + FbStorePart(dst,sizeof (FbBits) - 4,CARD8,xor); \ + break; \ + case (sizeof (FbBits) - 4) | (2 << (FB_SHIFT - 3)): \ + FbStorePart(dst,sizeof (FbBits) - 4,CARD16,xor); \ + break; \ + case (sizeof (FbBits) - 4) | (3 << (FB_SHIFT - 3)): \ + FbStorePart(dst,sizeof (FbBits) - 4,CARD16,xor); \ + FbStorePart(dst,sizeof (FbBits) - 2,CARD8,xor); \ + break; \ + case (sizeof (FbBits) - 4): \ + FbStorePart(dst,sizeof (FbBits) - 4,CARD32,xor); \ + break; + +#define FbDoRightMaskByteRRop6Cases(dst,xor) \ + case 4: \ + FbStorePart(dst,0,CARD32,xor); \ + break; \ + case 5: \ + FbStorePart(dst,0,CARD32,xor); \ + FbStorePart(dst,4,CARD8,xor); \ + break; \ + case 6: \ + FbStorePart(dst,0,CARD32,xor); \ + FbStorePart(dst,4,CARD16,xor); \ + break; \ + case 7: \ + FbStorePart(dst,0,CARD32,xor); \ + FbStorePart(dst,4,CARD16,xor); \ + FbStorePart(dst,6,CARD8,xor); \ + break; +#else +#define FbDoLeftMaskByteRRop6Cases(dst,xor) +#define FbDoRightMaskByteRRop6Cases(dst,xor) +#endif + +#define FbDoLeftMaskByteRRop(dst,lb,l,and,xor) { \ + switch (lb) { \ + FbDoLeftMaskByteRRop6Cases(dst,xor) \ + case (sizeof (FbBits) - 3) | (1 << (FB_SHIFT - 3)): \ + FbStorePart(dst,sizeof (FbBits) - 3,CARD8,xor); \ + break; \ + case (sizeof (FbBits) - 3) | (2 << (FB_SHIFT - 3)): \ + FbStorePart(dst,sizeof (FbBits) - 3,CARD8,xor); \ + FbStorePart(dst,sizeof (FbBits) - 2,CARD8,xor); \ + break; \ + case (sizeof (FbBits) - 2) | (1 << (FB_SHIFT - 3)): \ + FbStorePart(dst,sizeof (FbBits) - 2,CARD8,xor); \ + break; \ + case sizeof (FbBits) - 3: \ + FbStorePart(dst,sizeof (FbBits) - 3,CARD8,xor); \ + case sizeof (FbBits) - 2: \ + FbStorePart(dst,sizeof (FbBits) - 2,CARD16,xor); \ + break; \ + case sizeof (FbBits) - 1: \ + FbStorePart(dst,sizeof (FbBits) - 1,CARD8,xor); \ + break; \ + default: \ + *dst = FbDoMaskRRop(*dst, and, xor, l); \ + break; \ + } \ +} + +#define FbDoRightMaskByteRRop(dst,rb,r,and,xor) { \ + switch (rb) { \ + case 1: \ + FbStorePart(dst,0,CARD8,xor); \ + break; \ + case 2: \ + FbStorePart(dst,0,CARD16,xor); \ + break; \ + case 3: \ + FbStorePart(dst,0,CARD16,xor); \ + FbStorePart(dst,2,CARD8,xor); \ + break; \ + FbDoRightMaskByteRRop6Cases(dst,xor) \ + default: \ + *dst = FbDoMaskRRop (*dst, and, xor, r); \ + } \ +} + +#define FbMaskStip(x,w,l,n,r) { \ + n = (w); \ + r = FbRightStipMask((x)+n); \ + l = FbLeftStipMask(x); \ + if (l) { \ + n -= FB_STIP_UNIT - ((x) & FB_STIP_MASK); \ + if (n < 0) { \ + n = 0; \ + l &= r; \ + r = 0; \ + } \ + } \ + n >>= FB_STIP_SHIFT; \ +} + +/* + * These macros are used to transparently stipple + * in copy mode; the expected usage is with 'n' constant + * so all of the conditional parts collapse into a minimal + * sequence of partial word writes + * + * 'n' is the bytemask of which bytes to store, 'a' is the address + * of the FbBits base unit, 'o' is the offset within that unit + * + * The term "lane" comes from the hardware term "byte-lane" which + */ + +#define FbLaneCase1(n,a,o) ((n) == 0x01 ? \ + (*(CARD8 *) ((a)+FbPatternOffset(o,CARD8)) = \ + fgxor) : 0) +#define FbLaneCase2(n,a,o) ((n) == 0x03 ? \ + (*(CARD16 *) ((a)+FbPatternOffset(o,CARD16)) = \ + fgxor) : \ + ((void)FbLaneCase1((n)&1,a,o), \ + FbLaneCase1((n)>>1,a,(o)+1))) +#define FbLaneCase4(n,a,o) ((n) == 0x0f ? \ + (*(CARD32 *) ((a)+FbPatternOffset(o,CARD32)) = \ + fgxor) : \ + ((void)FbLaneCase2((n)&3,a,o), \ + FbLaneCase2((n)>>2,a,(o)+2))) +#define FbLaneCase8(n,a,o) ((n) == 0x0ff ? (*(FbBits *) ((a)+(o)) = fgxor) : \ + ((void)FbLaneCase4((n)&15,a,o), \ + FbLaneCase4((n)>>4,a,(o)+4))) + +#if FB_SHIFT == 6 +#define FbLaneCase(n,a) FbLaneCase8(n,(CARD8 *) (a),0) +#endif + +#if FB_SHIFT == 5 +#define FbLaneCase(n,a) FbLaneCase4(n,(CARD8 *) (a),0) +#endif + +/* Rotate a filled pixel value to the specified alignement */ +#define FbRot24(p,b) (FbScrRight(p,b) | FbScrLeft(p,24-(b))) +#define FbRot24Stip(p,b) (FbStipRight(p,b) | FbStipLeft(p,24-(b))) + +/* step a filled pixel value to the next/previous FB_UNIT alignment */ +#define FbNext24Pix(p) (FbRot24(p,(24-FB_UNIT%24))) +#define FbPrev24Pix(p) (FbRot24(p,FB_UNIT%24)) +#define FbNext24Stip(p) (FbRot24(p,(24-FB_STIP_UNIT%24))) +#define FbPrev24Stip(p) (FbRot24(p,FB_STIP_UNIT%24)) + +/* step a rotation value to the next/previous rotation value */ +#if FB_UNIT == 64 +#define FbNext24Rot(r) ((r) == 16 ? 0 : (r) + 8) +#define FbPrev24Rot(r) ((r) == 0 ? 16 : (r) - 8) + +#if IMAGE_BYTE_ORDER == MSBFirst +#define FbFirst24Rot(x) (((x) + 8) % 24) +#else +#define FbFirst24Rot(x) ((x) % 24) +#endif + +#endif + +#if FB_UNIT == 32 +#define FbNext24Rot(r) ((r) == 0 ? 16 : (r) - 8) +#define FbPrev24Rot(r) ((r) == 16 ? 0 : (r) + 8) + +#if IMAGE_BYTE_ORDER == MSBFirst +#define FbFirst24Rot(x) (((x) + 16) % 24) +#else +#define FbFirst24Rot(x) ((x) % 24) +#endif +#endif + +#define FbNext24RotStip(r) ((r) == 0 ? 16 : (r) - 8) +#define FbPrev24RotStip(r) ((r) == 16 ? 0 : (r) + 8) + +/* Whether 24-bit specific code is needed for this filled pixel value */ +#define FbCheck24Pix(p) ((p) == FbNext24Pix(p)) + +/* Macros for dealing with dashing */ + +#define FbDashDeclare \ + unsigned char *__dash, *__firstDash, *__lastDash + +#define FbDashInit(pGC,pPriv,dashOffset,dashlen,even) { \ + (even) = TRUE; \ + __firstDash = (pGC)->dash; \ + __lastDash = __firstDash + (pGC)->numInDashList; \ + (dashOffset) %= (pPriv)->dashLength; \ + \ + __dash = __firstDash; \ + while ((dashOffset) >= ((dashlen) = *__dash)) \ + { \ + (dashOffset) -= (dashlen); \ + (even) = 1-(even); \ + if (++__dash == __lastDash) \ + __dash = __firstDash; \ + } \ + (dashlen) -= (dashOffset); \ +} + +#define FbDashNext(dashlen) { \ + if (++__dash == __lastDash) \ + __dash = __firstDash; \ + (dashlen) = *__dash; \ +} + +/* as numInDashList is always even, this case can skip a test */ + +#define FbDashNextEven(dashlen) { \ + (dashlen) = *++__dash; \ +} + +#define FbDashNextOdd(dashlen) FbDashNext(dashlen) + +#define FbDashStep(dashlen,even) { \ + if (!--(dashlen)) { \ + FbDashNext(dashlen); \ + (even) = 1-(even); \ + } \ +} + +/* XXX fb*PrivateIndex should be static, but it breaks the ABI */ + +extern int fbGCPrivateIndex; + +extern int fbGetGCPrivateIndex(void); + +extern int fbWinPrivateIndex; + +extern int fbGetWinPrivateIndex(void); +extern const GCOps fbGCOps; + +extern const GCFuncs fbGCFuncs; + +extern int fbScreenPrivateIndex; + +extern int fbGetScreenPrivateIndex(void); + +/* private field of a screen */ +typedef struct { + unsigned char win32bpp; /* window bpp for 32-bpp images */ + unsigned char pix32bpp; /* pixmap bpp for 32-bpp images */ +} FbScreenPrivRec, *FbScreenPrivPtr; + +#define fbGetScreenPrivate(pScreen) ((FbScreenPrivPtr) \ + (pScreen)->devPrivates[fbGetScreenPrivateIndex()].ptr) + +/* private field of GC */ +typedef struct { + FbBits and, xor; /* reduced rop values */ + FbBits bgand, bgxor; /* for stipples */ + FbBits fg, bg, pm; /* expanded and filled */ + unsigned int dashLength; /* total of all dash elements */ + unsigned char oneRect; /* clip list is single rectangle */ + unsigned char evenStipple; /* stipple is even */ + unsigned char bpp; /* current drawable bpp */ +} FbGCPrivRec, *FbGCPrivPtr; + +#define fbGetGCPrivate(pGC) ((FbGCPrivPtr)\ + (pGC)->devPrivates[fbGetGCPrivateIndex()].ptr) + +#define fbGetCompositeClip(pGC) ((pGC)->pCompositeClip) +#define fbGetExpose(pGC) ((pGC)->fExpose) +#define fbGetFreeCompClip(pGC) ((pGC)->freeCompClip) +#define fbGetRotatedPixmap(pGC) ((pGC)->pRotatedPixmap) + +#define fbGetScreenPixmap(s) ((PixmapPtr) (s)->devPrivate) +#define fbGetWindowPixmap(pWin) ((PixmapPtr)\ + ((WindowPtr) (pWin))->devPrivates[fbGetWinPrivateIndex()].ptr) + +#define __fbPixDrawableX(pPix) 0 +#define __fbPixDrawableY(pPix) 0 + +#define __fbPixOffXWin(pPix) (__fbPixDrawableX(pPix)) +#define __fbPixOffYWin(pPix) (__fbPixDrawableY(pPix)) +#define __fbPixOffXPix(pPix) (__fbPixDrawableX(pPix)) +#define __fbPixOffYPix(pPix) (__fbPixDrawableY(pPix)) + +#define fbGetDrawable(pDrawable, pointer, stride, bpp, xoff, yoff) { \ + PixmapPtr _pPix; \ + if ((pDrawable)->type != DRAWABLE_PIXMAP) { \ + _pPix = fbGetWindowPixmap(pDrawable); \ + (xoff) = __fbPixOffXWin(_pPix); \ + (yoff) = __fbPixOffYWin(_pPix); \ + } else { \ + _pPix = (PixmapPtr) (pDrawable); \ + (xoff) = __fbPixOffXPix(_pPix); \ + (yoff) = __fbPixOffYPix(_pPix); \ + } \ + (pointer) = (FbBits *) _pPix->devPrivate.ptr; \ + (stride) = ((int) _pPix->devKind) / sizeof (FbBits); (void)(stride); \ + (bpp) = _pPix->drawable.bitsPerPixel; (void)(bpp); \ +} + +#define fbGetStipDrawable(pDrawable, pointer, stride, bpp, xoff, yoff) { \ + PixmapPtr _pPix; \ + if ((pDrawable)->type != DRAWABLE_PIXMAP) { \ + _pPix = fbGetWindowPixmap(pDrawable); \ + (xoff) = __fbPixOffXWin(_pPix); \ + (yoff) = __fbPixOffYWin(_pPix); \ + } else { \ + _pPix = (PixmapPtr) (pDrawable); \ + (xoff) = __fbPixOffXPix(_pPix); \ + (yoff) = __fbPixOffYPix(_pPix); \ + } \ + (pointer) = (FbStip *) _pPix->devPrivate.ptr; \ + (stride) = ((int) _pPix->devKind) / sizeof (FbStip); (void)(stride); \ + (bpp) = _pPix->drawable.bitsPerPixel; (void)(bpp); \ +} + +/* + * XFree86 empties the root BorderClip when the VT is inactive, + * here's a macro which uses that to disable GetImage and GetSpans + */ + +#define fbWindowEnabled(pWin) \ + REGION_NOTEMPTY(\ + &WindowTable[(pWin)->drawable.pScreen->myNum]->borderClip) + +#define fbDrawableEnabled(pDrawable) \ + ((pDrawable)->type == DRAWABLE_PIXMAP ? \ + TRUE : fbWindowEnabled((WindowPtr) pDrawable)) + + +#define FbPowerOfTwo(w) (((w) & ((w) - 1)) == 0) +/* + * Accelerated tiles are power of 2 width <= FB_UNIT + */ +#define FbEvenTile(w) ((w) <= FB_UNIT && FbPowerOfTwo(w)) +/* + * Accelerated stipples are power of 2 width and <= FB_UNIT/dstBpp + * with dstBpp a power of 2 as well + */ +#define FbEvenStip(w,bpp) ((w) * (bpp) <= FB_UNIT && FbPowerOfTwo(w) && FbPowerOfTwo(bpp)) + +/* + * fb24_32.c + */ +extern _X_EXPORT void + +fb24_32GetSpans(DrawablePtr pDrawable, + int wMax, + DDXPointPtr ppt, int *pwidth, int nspans, char *pchardstStart); + +extern _X_EXPORT void + +fb24_32SetSpans(DrawablePtr pDrawable, + GCPtr pGC, + char *src, + DDXPointPtr ppt, int *pwidth, int nspans, int fSorted); + +extern _X_EXPORT void + +fb24_32PutZImage(DrawablePtr pDrawable, + RegionPtr pClip, + int alu, + FbBits pm, + int x, + int y, int width, int height, CARD8 *src, FbStride srcStride); + +extern _X_EXPORT void + +fb24_32GetImage(DrawablePtr pDrawable, + int x, + int y, + int w, + int h, unsigned int format, unsigned long planeMask, char *d); + +extern _X_EXPORT void + +fb24_32CopyMtoN(DrawablePtr pSrcDrawable, + DrawablePtr pDstDrawable, + GCPtr pGC, + BoxPtr pbox, + int nbox, + int dx, + int dy, + Bool reverse, Bool upsidedown, Pixel bitplane, void *closure); + +extern _X_EXPORT PixmapPtr + fb24_32ReformatTile(PixmapPtr pOldTile, int bitsPerPixel); + +extern _X_EXPORT Bool + fb24_32CreateScreenResources(ScreenPtr pScreen); + +extern _X_EXPORT Bool + +fb24_32ModifyPixmapHeader(PixmapPtr pPixmap, + int width, + int height, + int depth, + int bitsPerPixel, int devKind, pointer pPixData); + +/* + * fballpriv.c + */ +extern _X_EXPORT Bool +fbAllocatePrivates(ScreenPtr pScreen, int *pGCIndex); + +/* + * fbarc.c + */ + +extern _X_EXPORT void +fbPolyArc(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc * parcs); + +/* + * fbbits.c + */ + +extern _X_EXPORT void + +fbBresSolid8(DrawablePtr pDrawable, + GCPtr pGC, + int dashOffset, + int signdx, + int signdy, + int axis, int x, int y, int e, int e1, int e3, int len); + +extern _X_EXPORT void + +fbBresDash8(DrawablePtr pDrawable, + GCPtr pGC, + int dashOffset, + int signdx, + int signdy, int axis, int x, int y, int e, int e1, int e3, int len); + +extern _X_EXPORT void + +fbDots8(FbBits * dst, + FbStride dstStride, + int dstBpp, + BoxPtr pBox, + xPoint * pts, + int npt, + int xorg, int yorg, int xoff, int yoff, FbBits and, FbBits xor); + +extern _X_EXPORT void + +fbArc8(FbBits * dst, + FbStride dstStride, + int dstBpp, xArc * arc, int dx, int dy, FbBits and, FbBits xor); + +extern _X_EXPORT void + +fbGlyph8(FbBits * dstLine, + FbStride dstStride, + int dstBpp, FbStip * stipple, FbBits fg, int height, int shift); + +extern _X_EXPORT void + +fbPolyline8(DrawablePtr pDrawable, + GCPtr pGC, int mode, int npt, DDXPointPtr ptsOrig); + +extern _X_EXPORT void + fbPolySegment8(DrawablePtr pDrawable, GCPtr pGC, int nseg, xSegment * pseg); + +extern _X_EXPORT void + +fbBresSolid16(DrawablePtr pDrawable, + GCPtr pGC, + int dashOffset, + int signdx, + int signdy, + int axis, int x, int y, int e, int e1, int e3, int len); + +extern _X_EXPORT void + +fbBresDash16(DrawablePtr pDrawable, + GCPtr pGC, + int dashOffset, + int signdx, + int signdy, + int axis, int x, int y, int e, int e1, int e3, int len); + +extern _X_EXPORT void + +fbDots16(FbBits * dst, + FbStride dstStride, + int dstBpp, + BoxPtr pBox, + xPoint * pts, + int npt, + int xorg, int yorg, int xoff, int yoff, FbBits and, FbBits xor); + +extern _X_EXPORT void + +fbArc16(FbBits * dst, + FbStride dstStride, + int dstBpp, xArc * arc, int dx, int dy, FbBits and, FbBits xor); + +extern _X_EXPORT void + +fbGlyph16(FbBits * dstLine, + FbStride dstStride, + int dstBpp, FbStip * stipple, FbBits fg, int height, int shift); + +extern _X_EXPORT void + +fbPolyline16(DrawablePtr pDrawable, + GCPtr pGC, int mode, int npt, DDXPointPtr ptsOrig); + +extern _X_EXPORT void + fbPolySegment16(DrawablePtr pDrawable, GCPtr pGC, int nseg, xSegment * pseg); + +extern _X_EXPORT void + +fbBresSolid24(DrawablePtr pDrawable, + GCPtr pGC, + int dashOffset, + int signdx, + int signdy, + int axis, int x, int y, int e, int e1, int e3, int len); + +extern _X_EXPORT void + +fbBresDash24(DrawablePtr pDrawable, + GCPtr pGC, + int dashOffset, + int signdx, + int signdy, + int axis, int x, int y, int e, int e1, int e3, int len); + +extern _X_EXPORT void + +fbDots24(FbBits * dst, + FbStride dstStride, + int dstBpp, + BoxPtr pBox, + xPoint * pts, + int npt, + int xorg, int yorg, int xoff, int yoff, FbBits and, FbBits xor); + +extern _X_EXPORT void + +fbArc24(FbBits * dst, + FbStride dstStride, + int dstBpp, xArc * arc, int dx, int dy, FbBits and, FbBits xor); + +extern _X_EXPORT void + +fbGlyph24(FbBits * dstLine, + FbStride dstStride, + int dstBpp, FbStip * stipple, FbBits fg, int height, int shift); + +extern _X_EXPORT void + +fbPolyline24(DrawablePtr pDrawable, + GCPtr pGC, int mode, int npt, DDXPointPtr ptsOrig); + +extern _X_EXPORT void + fbPolySegment24(DrawablePtr pDrawable, GCPtr pGC, int nseg, xSegment * pseg); + +extern _X_EXPORT void + +fbBresSolid32(DrawablePtr pDrawable, + GCPtr pGC, + int dashOffset, + int signdx, + int signdy, + int axis, int x, int y, int e, int e1, int e3, int len); + +extern _X_EXPORT void + +fbBresDash32(DrawablePtr pDrawable, + GCPtr pGC, + int dashOffset, + int signdx, + int signdy, + int axis, int x, int y, int e, int e1, int e3, int len); + +extern _X_EXPORT void + +fbDots32(FbBits * dst, + FbStride dstStride, + int dstBpp, + BoxPtr pBox, + xPoint * pts, + int npt, + int xorg, int yorg, int xoff, int yoff, FbBits and, FbBits xor); + +extern _X_EXPORT void + +fbArc32(FbBits * dst, + FbStride dstStride, + int dstBpp, xArc * arc, int dx, int dy, FbBits and, FbBits xor); + +extern _X_EXPORT void + +fbGlyph32(FbBits * dstLine, + FbStride dstStride, + int dstBpp, FbStip * stipple, FbBits fg, int height, int shift); +extern _X_EXPORT void + +fbPolyline32(DrawablePtr pDrawable, + GCPtr pGC, int mode, int npt, DDXPointPtr ptsOrig); + +extern _X_EXPORT void + fbPolySegment32(DrawablePtr pDrawable, GCPtr pGC, int nseg, xSegment * pseg); + +/* + * fbblt.c + */ +extern _X_EXPORT void + +fbBlt(FbBits * src, + FbStride srcStride, + int srcX, + FbBits * dst, + FbStride dstStride, + int dstX, + int width, + int height, int alu, FbBits pm, int bpp, Bool reverse, Bool upsidedown); + +extern _X_EXPORT void + +fbBlt24(FbBits * srcLine, + FbStride srcStride, + int srcX, + FbBits * dstLine, + FbStride dstStride, + int dstX, + int width, + int height, int alu, FbBits pm, Bool reverse, Bool upsidedown); + +extern _X_EXPORT void + fbBltStip(FbStip * src, FbStride srcStride, /* in FbStip units, not FbBits units */ + int srcX, FbStip * dst, FbStride dstStride, /* in FbStip units, not FbBits units */ + int dstX, int width, int height, int alu, FbBits pm, int bpp); + +/* + * fbbltone.c + */ +extern _X_EXPORT void + +fbBltOne(FbStip * src, + FbStride srcStride, + int srcX, + FbBits * dst, + FbStride dstStride, + int dstX, + int dstBpp, + int width, + int height, FbBits fgand, FbBits fbxor, FbBits bgand, FbBits bgxor); + +extern _X_EXPORT void + fbBltOne24(FbStip * src, FbStride srcStride, /* FbStip units per scanline */ + int srcX, /* bit position of source */ + FbBits * dst, FbStride dstStride, /* FbBits units per scanline */ + int dstX, /* bit position of dest */ + int dstBpp, /* bits per destination unit */ + int width, /* width in bits of destination */ + int height, /* height in scanlines */ + FbBits fgand, /* rrop values */ + FbBits fgxor, FbBits bgand, FbBits bgxor); + +extern _X_EXPORT void + +fbBltPlane(FbBits * src, + FbStride srcStride, + int srcX, + int srcBpp, + FbStip * dst, + FbStride dstStride, + int dstX, + int width, + int height, + FbStip fgand, + FbStip fgxor, FbStip bgand, FbStip bgxor, Pixel planeMask); + +/* + * fbcmap.c + */ +int + fbListInstalledColormaps(ScreenPtr pScreen, Colormap * pmaps); + +extern _X_EXPORT void + fbInstallColormap(ColormapPtr pmap); + +extern _X_EXPORT void + fbUninstallColormap(ColormapPtr pmap); + +extern _X_EXPORT void + +fbResolveColor(unsigned short *pred, + unsigned short *pgreen, + unsigned short *pblue, VisualPtr pVisual); + +extern _X_EXPORT Bool + fbInitializeColormap(ColormapPtr pmap); + +extern _X_EXPORT int + +fbExpandDirectColors(ColormapPtr pmap, + int ndef, xColorItem * indefs, xColorItem * outdefs); + +extern _X_EXPORT Bool + fbCreateDefColormap(ScreenPtr pScreen); + +extern _X_EXPORT void + fbClearVisualTypes(void); + +Bool + fbSetVisualTypes(int depth, int visuals, int bitsPerRGB); + +extern _X_EXPORT Bool + +fbSetVisualTypesAndMasks(int depth, int visuals, int bitsPerRGB, + Pixel redMask, Pixel greenMask, Pixel blueMask); + +extern _X_EXPORT Bool + +fbInitVisuals(VisualPtr * visualp, + DepthPtr * depthp, + int *nvisualp, + int *ndepthp, + int *rootDepthp, + VisualID * defaultVisp, unsigned long sizes, int bitsPerRGB); + +/* + * fbcopy.c + */ + +typedef void (*fbCopyProc) (DrawablePtr pSrcDrawable, + DrawablePtr pDstDrawable, + GCPtr pGC, + BoxPtr pDstBox, + int nbox, + int dx, + int dy, + Bool reverse, + Bool upsidedown, Pixel bitplane, void *closure); + +void + +fbCopyNtoN(DrawablePtr pSrcDrawable, + DrawablePtr pDstDrawable, + GCPtr pGC, + BoxPtr pbox, + int nbox, + int dx, + int dy, + Bool reverse, Bool upsidedown, Pixel bitplane, void *closure); + +extern _X_EXPORT void + +fbCopy1toN(DrawablePtr pSrcDrawable, + DrawablePtr pDstDrawable, + GCPtr pGC, + BoxPtr pbox, + int nbox, + int dx, + int dy, + Bool reverse, Bool upsidedown, Pixel bitplane, void *closure); + +extern _X_EXPORT void + +fbCopyNto1(DrawablePtr pSrcDrawable, + DrawablePtr pDstDrawable, + GCPtr pGC, + BoxPtr pbox, + int nbox, + int dx, + int dy, + Bool reverse, Bool upsidedown, Pixel bitplane, void *closure); + +void + +fbCopyRegion(DrawablePtr pSrcDrawable, + DrawablePtr pDstDrawable, + GCPtr pGC, + RegionPtr pDstRegion, + int dx, + int dy, fbCopyProc copyProc, Pixel bitPlane, void *closure); + +RegionPtr + +fbDoCopy(DrawablePtr pSrcDrawable, + DrawablePtr pDstDrawable, + GCPtr pGC, + int xIn, + int yIn, + int widthSrc, + int heightSrc, + int xOut, + int yOut, fbCopyProc copyProc, Pixel bitplane, void *closure); + +RegionPtr + +fbCopyArea(DrawablePtr pSrcDrawable, + DrawablePtr pDstDrawable, + GCPtr pGC, + int xIn, int yIn, int widthSrc, int heightSrc, int xOut, int yOut); + +RegionPtr + +fbCopyPlane(DrawablePtr pSrcDrawable, + DrawablePtr pDstDrawable, + GCPtr pGC, + int xIn, + int yIn, + int widthSrc, + int heightSrc, int xOut, int yOut, unsigned long bitplane); + +/* + * fbfill.c + */ +extern _X_EXPORT void + fbFill(DrawablePtr pDrawable, GCPtr pGC, int x, int y, int width, int height); + +extern _X_EXPORT void + +fbSolidBoxClipped(DrawablePtr pDrawable, + RegionPtr pClip, + int xa, int ya, int xb, int yb, FbBits and, FbBits xor); + +/* + * fbfillrect.c + */ +extern _X_EXPORT void + +fbPolyFillRect(DrawablePtr pDrawable, + GCPtr pGC, int nrectInit, xRectangle *prectInit); + +#define fbPolyFillArc miPolyFillArc + +#define fbFillPolygon miFillPolygon + +/* + * fbfillsp.c + */ +extern _X_EXPORT void + +fbFillSpans(DrawablePtr pDrawable, + GCPtr pGC, + int nInit, DDXPointPtr pptInit, int *pwidthInit, int fSorted); + +/* + * fbgc.c + */ + +extern _X_EXPORT Bool + fbCreateGC(GCPtr pGC); + +extern _X_EXPORT void + fbPadPixmap(PixmapPtr pPixmap); + +extern _X_EXPORT void + fbValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable); + +/* + * fbgetsp.c + */ +extern _X_EXPORT void + +fbGetSpans(DrawablePtr pDrawable, + int wMax, + DDXPointPtr ppt, int *pwidth, int nspans, char *pchardstStart); + +/* + * fbglyph.c + */ + +extern _X_EXPORT Bool + fbGlyphIn(RegionPtr pRegion, int x, int y, int width, int height); + +extern _X_EXPORT void + +fbPolyGlyphBlt(DrawablePtr pDrawable, + GCPtr pGC, + int x, + int y, + unsigned int nglyph, CharInfoPtr * ppci, pointer pglyphBase); + +extern _X_EXPORT void + +fbImageGlyphBlt(DrawablePtr pDrawable, + GCPtr pGC, + int x, + int y, + unsigned int nglyph, CharInfoPtr * ppci, pointer pglyphBase); + +/* + * fbimage.c + */ + +extern _X_EXPORT void + +fbPutImage(DrawablePtr pDrawable, + GCPtr pGC, + int depth, + int x, int y, int w, int h, int leftPad, int format, char *pImage); + +extern _X_EXPORT void + +fbPutZImage(DrawablePtr pDrawable, + RegionPtr pClip, + int alu, + FbBits pm, + int x, + int y, int width, int height, FbStip * src, FbStride srcStride); + +extern _X_EXPORT void + +fbPutXYImage(DrawablePtr pDrawable, + RegionPtr pClip, + FbBits fg, + FbBits bg, + FbBits pm, + int alu, + Bool opaque, + int x, + int y, + int width, int height, FbStip * src, FbStride srcStride, int srcX); + +extern _X_EXPORT void + +fbGetImage(DrawablePtr pDrawable, + int x, + int y, + int w, int h, unsigned int format, unsigned long planeMask, char *d); +/* + * fbline.c + */ + +extern _X_EXPORT void + +fbZeroLine(DrawablePtr pDrawable, + GCPtr pGC, int mode, int npt, DDXPointPtr ppt); + +extern _X_EXPORT void + fbZeroSegment(DrawablePtr pDrawable, GCPtr pGC, int nseg, xSegment * pSegs); + +extern _X_EXPORT void + +fbPolyLine(DrawablePtr pDrawable, + GCPtr pGC, int mode, int npt, DDXPointPtr ppt); + +extern _X_EXPORT void + fbFixCoordModePrevious(int npt, DDXPointPtr ppt); + +extern _X_EXPORT void + fbPolySegment(DrawablePtr pDrawable, GCPtr pGC, int nseg, xSegment * pseg); + +#define fbPolyRectangle miPolyRectangle + +/* + * fbpict.c + */ + +Bool + fbPictureInit(ScreenPtr pScreen, PictFormatPtr formats, int nformats); + +/* + * fbpixmap.c + */ + +PixmapPtr + +fbCreatePixmapBpp(ScreenPtr pScreen, int width, int height, int depth, int bpp); + +PixmapPtr + fbCreatePixmap(ScreenPtr pScreen, int width, int height, int depth); + +Bool + fbDestroyPixmap(PixmapPtr pPixmap); + +RegionPtr + fbPixmapToRegion(PixmapPtr pPix); + +/* + * fbpoint.c + */ + +void + +fbDots(FbBits * dstOrig, + FbStride dstStride, + int dstBpp, + BoxPtr pBox, + xPoint * pts, + int npt, + int xorg, int yorg, int xoff, int yoff, FbBits andOrig, FbBits xorOrig); + +extern _X_EXPORT void + +fbPolyPoint(DrawablePtr pDrawable, + GCPtr pGC, int mode, int npt, xPoint * pptInit); + +/* + * fbpush.c + */ +extern _X_EXPORT void + +fbPushPattern(DrawablePtr pDrawable, + GCPtr pGC, + FbStip * src, + FbStride srcStride, + int srcX, int x, int y, int width, int height); + +void + +fbPushFill(DrawablePtr pDrawable, + GCPtr pGC, + FbStip * src, + FbStride srcStride, int srcX, int x, int y, int width, int height); + +void + +fbPush1toN(DrawablePtr pSrcDrawable, + DrawablePtr pDstDrawable, + GCPtr pGC, + BoxPtr pbox, + int nbox, + int dx, + int dy, + Bool reverse, Bool upsidedown, Pixel bitplane, void *closure); + +void + +fbPushImage(DrawablePtr pDrawable, + GCPtr pGC, + FbStip * src, + FbStride srcStride, int srcX, int x, int y, int width, int height); + +void + +fbPushPixels(GCPtr pGC, + PixmapPtr pBitmap, + DrawablePtr pDrawable, int dx, int dy, int xOrg, int yOrg); + +/* + * fbscreen.c + */ + +Bool + fbCloseScreen(int indx, ScreenPtr pScreen); + +Bool + fbRealizeFont(ScreenPtr pScreen, FontPtr pFont); + +Bool + fbUnrealizeFont(ScreenPtr pScreen, FontPtr pFont); + +void + +fbQueryBestSize(int class, + unsigned short *width, unsigned short *height, + ScreenPtr pScreen); + +PixmapPtr + _fbGetWindowPixmap(WindowPtr pWindow); + +void + _fbSetWindowPixmap(WindowPtr pWindow, PixmapPtr pPixmap); + +Bool + fbSetupScreen(ScreenPtr pScreen, pointer pbits, /* pointer to screen bitmap */ + int xsize, /* in pixels */ + int ysize, int dpix, /* dots per inch */ + int dpiy, int width, /* pixel width of frame buffer */ + int bpp); /* bits per pixel of frame buffer */ + +Bool + +fbFinishScreenInit(ScreenPtr pScreen, + pointer pbits, + int xsize, + int ysize, int dpix, int dpiy, int width, int bpp); + +/* + * fbseg.c + */ +typedef void FbBres(DrawablePtr pDrawable, + GCPtr pGC, + int dashOffset, + int signdx, + int signdy, + int axis, int x, int y, int e, int e1, int e3, int len); + +FbBres fbBresSolid, fbBresDash, fbBresFill, fbBresFillDash; + +/* + * fbsetsp.c + */ + +void + +fbSetSpans(DrawablePtr pDrawable, + GCPtr pGC, + char *src, DDXPointPtr ppt, int *pwidth, int nspans, int fSorted); + +FbBres *fbSelectBres(DrawablePtr pDrawable, GCPtr pGC); + +void + +fbBres(DrawablePtr pDrawable, + GCPtr pGC, + int dashOffset, + int signdx, + int signdy, int axis, int x, int y, int e, int e1, int e3, int len); + +extern _X_EXPORT void + +fbSegment(DrawablePtr pDrawable, + GCPtr pGC, + int xa, int ya, int xb, int yb, Bool drawLast, int *dashOffset); + +/* + * fbsolid.c + */ + +extern _X_EXPORT void + +fbSolid(FbBits * dst, + FbStride dstStride, + int dstX, int bpp, int width, int height, FbBits and, FbBits xor); + +extern _X_EXPORT void + +fbSolid24(FbBits * dst, + FbStride dstStride, + int dstX, int width, int height, FbBits and, FbBits xor); + +/* + * fbstipple.c + */ + +extern _X_EXPORT void + fbTransparentSpan(FbBits * dst, FbBits stip, FbBits fgxor, int n); + +extern _X_EXPORT void + +fbEvenStipple(FbBits * dst, + FbStride dstStride, + int dstX, + int dstBpp, + int width, + int height, + FbStip * stip, + FbStride stipStride, + int stipHeight, + FbBits fgand, + FbBits fgxor, FbBits bgand, FbBits bgxor, int xRot, int yRot); + +extern _X_EXPORT void + +fbOddStipple(FbBits * dst, + FbStride dstStride, + int dstX, + int dstBpp, + int width, + int height, + FbStip * stip, + FbStride stipStride, + int stipWidth, + int stipHeight, + FbBits fgand, + FbBits fgxor, FbBits bgand, FbBits bgxor, int xRot, int yRot); + +extern _X_EXPORT void + +fbStipple(FbBits * dst, + FbStride dstStride, + int dstX, + int dstBpp, + int width, + int height, + FbStip * stip, + FbStride stipStride, + int stipWidth, + int stipHeight, + Bool even, + FbBits fgand, + FbBits fgxor, FbBits bgand, FbBits bgxor, int xRot, int yRot); + +/* + * fbtile.c + */ + +extern _X_EXPORT void + +fbEvenTile(FbBits * dst, + FbStride dstStride, + int dstX, + int width, + int height, + FbBits * tile, + int tileHeight, int alu, FbBits pm, int xRot, int yRot); + +void + +fbOddTile(FbBits * dst, + FbStride dstStride, + int dstX, + int width, + int height, + FbBits * tile, + FbStride tileStride, + int tileWidth, + int tileHeight, int alu, FbBits pm, int bpp, int xRot, int yRot); + +extern _X_EXPORT void + +fbTile(FbBits * dst, + FbStride dstStride, + int dstX, + int width, + int height, + FbBits * tile, + FbStride tileStride, + int tileWidth, + int tileHeight, int alu, FbBits pm, int bpp, int xRot, int yRot); + +/* + * fbutil.c + */ +FbBits fbReplicatePixel(Pixel p, int bpp); + +/* + * fbwindow.c + */ + +Bool + fbCreateWindow(WindowPtr pWin); + +Bool + fbDestroyWindow(WindowPtr pWin); + +Bool + fbMapWindow(WindowPtr pWindow); + +Bool + fbPositionWindow(WindowPtr pWin, int x, int y); + +Bool + fbUnmapWindow(WindowPtr pWindow); + +void + +fbCopyWindowProc(DrawablePtr pSrcDrawable, + DrawablePtr pDstDrawable, + GCPtr pGC, + BoxPtr pbox, + int nbox, + int dx, + int dy, + Bool reverse, Bool upsidedown, Pixel bitplane, void *closure); + +void + fbCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc); + +Bool + fbChangeWindowAttributes(WindowPtr pWin, unsigned long mask); + +void + +fbFillRegionSolid(DrawablePtr pDrawable, + RegionPtr pRegion, FbBits and, FbBits xor); + +void + fbFillRegionTiled(DrawablePtr pDrawable, RegionPtr pRegion, PixmapPtr pTile); + +void + fbPaintWindow(WindowPtr pWin, RegionPtr pRegion, int what); + +#endif /* _FB_H_ */ diff --git a/fb/fb24_32.c b/fb/fb24_32.c new file mode 100644 index 0000000..571eed6 --- /dev/null +++ b/fb/fb24_32.c @@ -0,0 +1,586 @@ +/* + * + * Copyright © 2000 SuSE, 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, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * 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. + * + * Author: Keith Packard, SuSE, Inc. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include + +#include "fb.h" + +/* X apps don't like 24bpp images, this code exposes 32bpp images */ + +/* + * These two functions do a full CopyArea while reformatting + * the data between 24 and 32bpp. They try to go a bit faster + * by reading/writing aligned CARD32s where it's easy + */ + +#define Get8(a) ((CARD32) *(a)) + +#if BITMAP_BIT_ORDER == MSBFirst +#define Get24(a) ((Get8(a) << 16) | (Get8((a)+1) << 8) | Get8((a)+2)) +#define Put24(a,p) (((a)[0] = (CARD8) ((p) >> 16)), \ + ((a)[1] = (CARD8) ((p) >> 8)), \ + ((a)[2] = (CARD8) (p))) +#else +#define Get24(a) (Get8(a) | (Get8((a)+1) << 8) | (Get8((a)+2)<<16)) +#define Put24(a,p) (((a)[0] = (CARD8) (p)), \ + ((a)[1] = (CARD8) ((p) >> 8)), \ + ((a)[2] = (CARD8) ((p) >> 16))) +#endif + +typedef void (*fb24_32BltFunc) (CARD8 *srcLine, + FbStride srcStride, + int srcX, + CARD8 *dstLine, + FbStride dstStride, + int dstX, + int width, int height, int alu, FbBits pm); + +static void +fb24_32BltDown(CARD8 *srcLine, + FbStride srcStride, + int srcX, + CARD8 *dstLine, + FbStride dstStride, + int dstX, int width, int height, int alu, FbBits pm) +{ + CARD32 *src; + + CARD8 *dst; + + int w; + + Bool destInvarient; + + CARD32 pixel, dpixel; + + FbDeclareMergeRop(); + + srcLine += srcX * 4; + dstLine += dstX * 3; + + FbInitializeMergeRop(alu, (pm | ~(FbBits) 0xffffff)); + destInvarient = FbDestInvarientMergeRop(); + + while (height--) { + src = (CARD32 *) srcLine; + dst = dstLine; + srcLine += srcStride; + dstLine += dstStride; + w = width; + if (destInvarient) { + while (((long) dst & 3) && w) { + w--; + pixel = *src++; + pixel = FbDoDestInvarientMergeRop(pixel); + Put24(dst, pixel); + dst += 3; + } + /* Do four aligned pixels at a time */ + while (w >= 4) { + CARD32 s0, s1; + + s0 = *src++; + s0 = FbDoDestInvarientMergeRop(s0); + s1 = *src++; + s1 = FbDoDestInvarientMergeRop(s1); +#if BITMAP_BIT_ORDER == LSBFirst + *(CARD32 *) (dst) = (s0 & 0xffffff) | (s1 << 24); +#else + *(CARD32 *) (dst) = (s0 << 8) | ((s1 & 0xffffff) >> 16); +#endif + s0 = *src++; + s0 = FbDoDestInvarientMergeRop(s0); +#if BITMAP_BIT_ORDER == LSBFirst + *(CARD32 *) (dst + 4) = ((s1 & 0xffffff) >> 8) | (s0 << 16); +#else + *(CARD32 *) (dst + 4) = (s1 << 16) | ((s0 & 0xffffff) >> 8); +#endif + s1 = *src++; + s1 = FbDoDestInvarientMergeRop(s1); +#if BITMAP_BIT_ORDER == LSBFirst + *(CARD32 *) (dst + 8) = ((s0 & 0xffffff) >> 16) | (s1 << 8); +#else + *(CARD32 *) (dst + 8) = (s0 << 24) | (s1 & 0xffffff); +#endif + dst += 12; + w -= 4; + } + while (w--) { + pixel = *src++; + pixel = FbDoDestInvarientMergeRop(pixel); + Put24(dst, pixel); + dst += 3; + } + } + else { + while (w--) { + pixel = *src++; + dpixel = Get24(dst); + pixel = FbDoMergeRop(pixel, dpixel); + Put24(dst, pixel); + dst += 3; + } + } + } +} + +static void +fb24_32BltUp(CARD8 *srcLine, + FbStride srcStride, + int srcX, + CARD8 *dstLine, + FbStride dstStride, + int dstX, int width, int height, int alu, FbBits pm) +{ + CARD8 *src; + + CARD32 *dst; + + int w; + + Bool destInvarient; + + CARD32 pixel; + + FbDeclareMergeRop(); + + FbInitializeMergeRop(alu, (pm | (~(FbBits) 0xffffff))); + destInvarient = FbDestInvarientMergeRop(); + + srcLine += srcX * 3; + dstLine += dstX * 4; + + while (height--) { + w = width; + src = srcLine; + dst = (CARD32 *) dstLine; + srcLine += srcStride; + dstLine += dstStride; + if (destInvarient) { + while (((long) src & 3) && w) { + w--; + pixel = Get24(src); + src += 3; + *dst++ = FbDoDestInvarientMergeRop(pixel); + } + /* Do four aligned pixels at a time */ + while (w >= 4) { + CARD32 s0, s1; + + s0 = *(CARD32 *) (src); +#if BITMAP_BIT_ORDER == LSBFirst + pixel = s0 & 0xffffff; +#else + pixel = s0 >> 8; +#endif + *dst++ = FbDoDestInvarientMergeRop(pixel); + s1 = *(CARD32 *) (src + 4); +#if BITMAP_BIT_ORDER == LSBFirst + pixel = (s0 >> 24) | ((s1 << 8) & 0xffffff); +#else + pixel = ((s0 << 16) & 0xffffff) | (s1 >> 16); +#endif + *dst++ = FbDoDestInvarientMergeRop(pixel); + s0 = *(CARD32 *) (src + 8); +#if BITMAP_BIT_ORDER == LSBFirst + pixel = (s1 >> 16) | ((s0 << 16) & 0xffffff); +#else + pixel = ((s1 << 8) & 0xffffff) | (s0 >> 24); +#endif + *dst++ = FbDoDestInvarientMergeRop(pixel); +#if BITMAP_BIT_ORDER == LSBFirst + pixel = s0 >> 8; +#else + pixel = s0 & 0xffffff; +#endif + *dst++ = FbDoDestInvarientMergeRop(pixel); + src += 12; + w -= 4; + } + while (w) { + w--; + pixel = Get24(src); + src += 3; + *dst++ = FbDoDestInvarientMergeRop(pixel); + } + } + else { + while (w--) { + pixel = Get24(src); + src += 3; + *dst = FbDoMergeRop(pixel, *dst); + dst++; + } + } + } +} + +/* + * Spans functions; probably unused. + */ +void +fb24_32GetSpans(DrawablePtr pDrawable, + int wMax, + DDXPointPtr ppt, int *pwidth, int nspans, char *pchardstStart) +{ + FbBits *srcBits; + + CARD8 *src; + + FbStride srcStride; + + int srcBpp; + + int srcXoff, srcYoff; + + CARD8 *dst; + + fbGetDrawable(pDrawable, srcBits, srcStride, srcBpp, srcXoff, srcYoff); + src = (CARD8 *) srcBits; + srcStride *= sizeof(FbBits); + + while (nspans--) { + dst = (CARD8 *) pchardstStart; + fb24_32BltUp(src + (ppt->y + srcYoff) * srcStride, srcStride, + ppt->x + srcXoff, + dst, 1, 0, *pwidth, 1, GXcopy, FB_ALLONES); + + pchardstStart += PixmapBytePad(*pwidth, pDrawable->depth); + ppt++; + pwidth++; + } +} + +void +fb24_32SetSpans(DrawablePtr pDrawable, + GCPtr pGC, + char *src, + DDXPointPtr ppt, int *pwidth, int nspans, int fSorted) +{ + FbGCPrivPtr pPriv = fbGetGCPrivate(pGC); + + RegionPtr pClip = fbGetCompositeClip(pGC); + + FbBits *dstBits; + + CARD8 *dst, *d, *s; + + FbStride dstStride; + + int dstBpp; + + int dstXoff, dstYoff; + + BoxPtr pbox; + + int n; + + int x1, x2; + + fbGetDrawable(pDrawable, dstBits, dstStride, dstBpp, dstXoff, dstYoff); + dst = (CARD8 *) dstBits; + dstStride *= sizeof(FbBits); + while (nspans--) { + d = dst + (ppt->y + dstYoff) * dstStride; + s = (CARD8 *) src; + n = REGION_NUM_RECTS(pClip); + pbox = REGION_RECTS(pClip); + while (n--) { + if (pbox->y1 > ppt->y) + break; + if (pbox->y2 > ppt->y) { + x1 = ppt->x; + x2 = x1 + *pwidth; + if (pbox->x1 > x1) + x1 = pbox->x1; + if (pbox->x2 < x2) + x2 = pbox->x2; + if (x1 < x2) + fb24_32BltDown(s, + 0, + (x1 - ppt->x), + d, + dstStride, + x1 + dstXoff, + (x2 - x1), 1, pGC->alu, pPriv->pm); + } + } + src += PixmapBytePad(*pwidth, pDrawable->depth); + ppt++; + pwidth++; + } +} + +/* + * Clip and put 32bpp Z-format images to a 24bpp drawable + */ +void +fb24_32PutZImage(DrawablePtr pDrawable, + RegionPtr pClip, + int alu, + FbBits pm, + int x, + int y, int width, int height, CARD8 *src, FbStride srcStride) +{ + FbBits *dstBits; + + CARD8 *dst; + + FbStride dstStride; + + int dstBpp; + + int dstXoff, dstYoff; + + int nbox; + + BoxPtr pbox; + + int x1, y1, x2, y2; + + fbGetDrawable(pDrawable, dstBits, dstStride, dstBpp, dstXoff, dstYoff); + dstStride *= sizeof(FbBits); + dst = (CARD8 *) dstBits; + + for (nbox = REGION_NUM_RECTS(pClip), + pbox = REGION_RECTS(pClip); nbox--; pbox++) { + x1 = x; + y1 = y; + x2 = x + width; + y2 = y + height; + if (x1 < pbox->x1) + x1 = pbox->x1; + if (y1 < pbox->y1) + y1 = pbox->y1; + if (x2 > pbox->x2) + x2 = pbox->x2; + if (y2 > pbox->y2) + y2 = pbox->y2; + if (x1 >= x2 || y1 >= y2) + continue; + fb24_32BltDown(src + (y1 - y) * srcStride, + srcStride, + (x1 - x), + dst + (y1 + dstYoff) * dstStride, + dstStride, x1 + dstXoff, (x2 - x1), (y2 - y1), alu, pm); + } +} + +void +fb24_32GetImage(DrawablePtr pDrawable, + int x, + int y, + int w, + int h, unsigned int format, unsigned long planeMask, char *d) +{ + FbBits *srcBits; + + CARD8 *src; + + FbStride srcStride; + + int srcBpp; + + int srcXoff, srcYoff; + + FbStride dstStride; + + FbBits pm; + + fbGetDrawable(pDrawable, srcBits, srcStride, srcBpp, srcXoff, srcYoff); + src = (CARD8 *) srcBits; + srcStride *= sizeof(FbBits); + + x += pDrawable->x; + y += pDrawable->y; + + pm = fbReplicatePixel(planeMask, 32); + dstStride = PixmapBytePad(w, pDrawable->depth); + if (pm != FB_ALLONES) + memset(d, 0, dstStride * h); + fb24_32BltUp(src + (y + srcYoff) * srcStride, srcStride, x + srcXoff, + (CARD8 *) d, dstStride, 0, w, h, GXcopy, pm); +} + +void +fb24_32CopyMtoN(DrawablePtr pSrcDrawable, + DrawablePtr pDstDrawable, + GCPtr pGC, + BoxPtr pbox, + int nbox, + int dx, + int dy, + Bool reverse, Bool upsidedown, Pixel bitplane, void *closure) +{ + FbGCPrivPtr pPriv = fbGetGCPrivate(pGC); + + FbBits *srcBits; + + CARD8 *src; + + FbStride srcStride; + + int srcBpp; + + FbBits *dstBits; + + CARD8 *dst; + + FbStride dstStride; + + int dstBpp; + + fb24_32BltFunc blt; + + int srcXoff, srcYoff; + + int dstXoff, dstYoff; + + fbGetDrawable(pSrcDrawable, srcBits, srcStride, srcBpp, srcXoff, srcYoff); + src = (CARD8 *) srcBits; + srcStride *= sizeof(FbBits); + fbGetDrawable(pDstDrawable, dstBits, dstStride, dstBpp, dstXoff, dstYoff); + dst = (CARD8 *) dstBits; + dstStride *= sizeof(FbBits); + if (srcBpp == 24) + blt = fb24_32BltUp; + else + blt = fb24_32BltDown; + + while (nbox--) { + (*blt) (src + (pbox->y1 + dy + srcYoff) * srcStride, + srcStride, + (pbox->x1 + dx + srcXoff), + dst + (pbox->y1 + dstYoff) * dstStride, + dstStride, + (pbox->x1 + dstXoff), + (pbox->x2 - pbox->x1), + (pbox->y2 - pbox->y1), pGC->alu, pPriv->pm); + pbox++; + } +} + +PixmapPtr +fb24_32ReformatTile(PixmapPtr pOldTile, int bitsPerPixel) +{ + ScreenPtr pScreen = pOldTile->drawable.pScreen; + + PixmapPtr pNewTile; + + FbBits *old, *new; + + FbStride oldStride, newStride; + + int oldBpp, newBpp; + + fb24_32BltFunc blt; + + int oldXoff _X_UNUSED, oldYoff _X_UNUSED; + int newXoff _X_UNUSED, newYoff _X_UNUSED; + + pNewTile = fbCreatePixmapBpp(pScreen, + pOldTile->drawable.width, + pOldTile->drawable.height, + pOldTile->drawable.depth, bitsPerPixel); + if (!pNewTile) + return 0; + fbGetDrawable(&pOldTile->drawable, + old, oldStride, oldBpp, oldXoff, oldYoff); + fbGetDrawable(&pNewTile->drawable, + new, newStride, newBpp, newXoff, newYoff); + if (oldBpp == 24) + blt = fb24_32BltUp; + else + blt = fb24_32BltDown; + + (*blt) ((CARD8 *) old, + oldStride * sizeof(FbBits), + 0, + (CARD8 *) new, + newStride * sizeof(FbBits), + 0, + pOldTile->drawable.width, + pOldTile->drawable.height, GXcopy, FB_ALLONES); + + return pNewTile; +} + +typedef struct { + pointer pbits; + int width; +} miScreenInitParmsRec, *miScreenInitParmsPtr; + +Bool +fb24_32CreateScreenResources(ScreenPtr pScreen) +{ + miScreenInitParmsPtr pScrInitParms; + + int pitch; + + Bool retval; + + /* get the pitch before mi destroys it */ + pScrInitParms = (miScreenInitParmsPtr) pScreen->devPrivate; + pitch = BitmapBytePad(pScrInitParms->width * 24); + + if ((retval = miCreateScreenResources(pScreen))) { + /* fix the screen pixmap */ + PixmapPtr pPix = (PixmapPtr) pScreen->devPrivate; + + pPix->drawable.bitsPerPixel = 24; + pPix->devKind = pitch; + } + + return retval; +} + +Bool +fb24_32ModifyPixmapHeader(PixmapPtr pPixmap, + int width, + int height, + int depth, + int bitsPerPixel, int devKind, pointer pPixData) +{ + int bpp, w; + + if (!pPixmap) + return FALSE; + bpp = bitsPerPixel; + if (bpp <= 0) + bpp = pPixmap->drawable.bitsPerPixel; + if (bpp == 24) { + if (devKind < 0) { + w = width; + if (w <= 0) + w = pPixmap->drawable.width; + devKind = BitmapBytePad(w * 24); + } + } + return miModifyPixmapHeader(pPixmap, width, height, depth, bitsPerPixel, + devKind, pPixData); +} diff --git a/fb/fb24_32.h b/fb/fb24_32.h new file mode 100644 index 0000000..ecc3acd --- /dev/null +++ b/fb/fb24_32.h @@ -0,0 +1,44 @@ +/* + * Copyright © 2000 SuSE, 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, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * 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. + * + * Author: Keith Packard, SuSE, Inc. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#ifndef _FB24_32_H_ +#define _FB24_32_H_ + +Bool + +fb24_32FinishScreenInit(ScreenPtr pScreen, + pointer pbits, + int xsize, + int ysize, int dpix, int dpiy, int width, int bpp); + +Bool + +fb24_32ScreenInit(ScreenPtr pScreen, + pointer pbits, + int xsize, int ysize, int dpix, int dpiy, int width, int bpp); + +#endif diff --git a/fb/fballpriv.c b/fb/fballpriv.c new file mode 100644 index 0000000..3525f5f --- /dev/null +++ b/fb/fballpriv.c @@ -0,0 +1,82 @@ +/* + * + * Copyright © 1998 Keith Packard + * + * 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, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "fb.h" + +int fbScreenPrivateIndex; + +int +fbGetScreenPrivateIndex(void) +{ + return fbScreenPrivateIndex; +} +int fbGCPrivateIndex; + +int +fbGetGCPrivateIndex(void) +{ + return fbGCPrivateIndex; +} + +int fbWinPrivateIndex; + +int +fbGetWinPrivateIndex(void) +{ + return fbWinPrivateIndex; +} +int fbGeneration; + + +Bool +fbAllocatePrivates(ScreenPtr pScreen, int *pGCIndex) +{ + if (fbGeneration != serverGeneration) { + fbGCPrivateIndex = miAllocateGCPrivateIndex(); + fbWinPrivateIndex = AllocateWindowPrivateIndex(); + fbScreenPrivateIndex = AllocateScreenPrivateIndex(); + if (fbScreenPrivateIndex == -1) + return FALSE; + + fbGeneration = serverGeneration; + } + if (pGCIndex) + *pGCIndex = fbGCPrivateIndex; + if (!AllocateGCPrivate(pScreen, fbGCPrivateIndex, sizeof(FbGCPrivRec))) + return FALSE; + if (!AllocateWindowPrivate(pScreen, fbWinPrivateIndex, 0)) + return FALSE; + { + FbScreenPrivPtr pScreenPriv; + + pScreenPriv = malloc(sizeof(FbScreenPrivRec)); + if (!pScreenPriv) + return FALSE; + pScreen->devPrivates[fbScreenPrivateIndex].ptr = (pointer) pScreenPriv; + } + return TRUE; +} diff --git a/fb/fbarc.c b/fb/fbarc.c new file mode 100644 index 0000000..264c5ca --- /dev/null +++ b/fb/fbarc.c @@ -0,0 +1,117 @@ +/* + * + * Copyright © 1998 Keith Packard + * + * 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, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "fb.h" +#include "mizerarc.h" +#include + +typedef void (*FbArc) (FbBits * dst, + FbStride dstStride, + int dstBpp, + xArc * arc, int dx, int dy, FbBits and, FbBits xor); + +void +fbPolyArc(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc * parcs) +{ + FbArc arc; + + if (pGC->lineWidth == 0) { + arc = 0; + if (pGC->lineStyle == LineSolid && pGC->fillStyle == FillSolid) { + switch (pDrawable->bitsPerPixel) { + case 8: + arc = fbArc8; + break; + case 16: + arc = fbArc16; + break; + case 24: + arc = fbArc24; + break; + case 32: + arc = fbArc32; + break; + } + } + if (arc) { + FbGCPrivPtr pPriv = fbGetGCPrivate(pGC); + + FbBits *dst; + + FbStride dstStride; + + int dstBpp; + + int dstXoff, dstYoff; + + BoxRec box; + + int x2, y2; + + RegionPtr cclip; + + cclip = fbGetCompositeClip(pGC); + fbGetDrawable(pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); + while (narcs--) { + if (miCanZeroArc(parcs)) { + box.x1 = parcs->x + pDrawable->x; + box.y1 = parcs->y + pDrawable->y; + /* + * Because box.x2 and box.y2 get truncated to 16 bits, and the + * RECT_IN_REGION test treats the resulting number as a signed + * integer, the RECT_IN_REGION test alone can go the wrong way. + * This can result in a server crash because the rendering + * routines in this file deal directly with cpu addresses + * of pixels to be stored, and do not clip or otherwise check + * that all such addresses are within their respective pixmaps. + * So we only allow the RECT_IN_REGION test to be used for + * values that can be expressed correctly in a signed short. + */ + x2 = box.x1 + (int) parcs->width + 1; + box.x2 = x2; + y2 = box.y1 + (int) parcs->height + 1; + box.y2 = y2; + if ((x2 <= SHRT_MAX) && (y2 <= SHRT_MAX) && + (RECT_IN_REGION(cclip, &box) == + rgnIN)) + (*arc) (dst, dstStride, dstBpp, parcs, + pDrawable->x + dstXoff, pDrawable->y + dstYoff, + pPriv->and, pPriv->xor); + else + miZeroPolyArc(pDrawable, pGC, 1, parcs); + } + else + miPolyArc(pDrawable, pGC, 1, parcs); + parcs++; + } + } + else + miZeroPolyArc(pDrawable, pGC, narcs, parcs); + } + else + miPolyArc(pDrawable, pGC, narcs, parcs); +} diff --git a/fb/fbbits.c b/fb/fbbits.c new file mode 100644 index 0000000..b3ba529 --- /dev/null +++ b/fb/fbbits.c @@ -0,0 +1,175 @@ +/* + * + * Copyright © 1998 Keith Packard + * + * 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, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "fb.h" +#include "miline.h" +#include "mizerarc.h" + +#undef BRESSOLID +#undef BRESDASH +#undef DOTS +#undef ARC +#undef GLYPH +#undef BITS +#undef BITS2 +#undef BITS4 + +#define BRESSOLID fbBresSolid8 +#define BRESDASH fbBresDash8 +#define DOTS fbDots8 +#define ARC fbArc8 +#define GLYPH fbGlyph8 +#define POLYLINE fbPolyline8 +#define POLYSEGMENT fbPolySegment8 +#define BITS BYTE +#define BITS2 CARD16 +#define BITS4 CARD32 + +#include "fbbits.h" + +#undef BRESSOLID +#undef BRESDASH +#undef DOTS +#undef ARC +#undef GLYPH +#undef POLYLINE +#undef POLYSEGMENT +#undef BITS +#undef BITS2 +#undef BITS4 + +#define BRESSOLID fbBresSolid16 +#define BRESDASH fbBresDash16 +#define DOTS fbDots16 +#define ARC fbArc16 +#define GLYPH fbGlyph16 +#define POLYLINE fbPolyline16 +#define POLYSEGMENT fbPolySegment16 +#define BITS CARD16 +#define BITS2 CARD32 +#if FB_SHIFT == 6 +#define BITS4 FbBits +#endif + +#include "fbbits.h" + +#undef BRESSOLID +#undef BRESDASH +#undef DOTS +#undef ARC +#undef GLYPH +#undef POLYLINE +#undef POLYSEGMENT +#undef BITS +#undef BITS2 +#if FB_SHIFT == 6 +#undef BITS4 +#endif + +#define BRESSOLID fbBresSolid24 +#define BRESDASH fbBresDash24 +#define DOTS fbDots24 +#define ARC fbArc24 +#define POLYLINE fbPolyline24 +#define POLYSEGMENT fbPolySegment24 + +#define BITS CARD32 +#define BITSUNIT BYTE +#define BITSMUL 3 + +#define FbDoTypeStore(b,t,x,s) (*((t *) (b)) = (x) >> (s)) +#define FbDoTypeRRop(b,t,a,x,s) (*((t *) (b)) = FbDoRRop(*((t *) (b)),\ + (a) >> (s), \ + (x) >> (s))) +#define FbDoTypeMaskRRop(b,t,a,x,m,s) (*((t *) (b)) = FbDoMaskRRop(*((t *) (b)),\ + (a) >> (s), \ + (x) >> (s), \ + (m) >> (s)) +#if BITMAP_BIT_ORDER == LSBFirst +#define BITSSTORE(b,x) ((unsigned long) (b) & 1 ? \ + (FbDoTypeStore (b, CARD8, x, 0), \ + FbDoTypeStore ((b) + 1, CARD16, x, 8)) : \ + (FbDoTypeStore (b, CARD16, x, 0), \ + FbDoTypeStore ((b) + 2, CARD8, x, 16))) +#define BITSRROP(b,a,x) ((unsigned long) (b) & 1 ? \ + (FbDoTypeRRop(b,CARD8,a,x,0), \ + FbDoTypeRRop((b)+1,CARD16,a,x,8)) : \ + (FbDoTypeRRop(b,CARD16,a,x,0), \ + FbDoTypeRRop((b)+2,CARD8,a,x,16))) +#else +#define BITSSTORE(b,x) ((unsigned long) (b) & 1 ? \ + (FbDoTypeStore (b, CARD8, x, 16), \ + FbDoTypeStore ((b) + 1, CARD16, x, 0)) : \ + (FbDoTypeStore (b, CARD16, x, 8), \ + FbDoTypeStore ((b) + 2, CARD8, x, 0))) +#define BITSRROP(b,a,x) ((unsigned long) (b) & 1 ? \ + (FbDoTypeRRop (b, CARD8, a, x, 16), \ + FbDoTypeRRop ((b) + 1, CARD16, a, x, 0)) : \ + (FbDoTypeRRop (b, CARD16, a, x, 8), \ + FbDoTypeRRop ((b) + 2, CARD8, a, x, 0))) +#endif + +#include "fbbits.h" + +#undef BITSSTORE +#undef BITSRROP +#undef BITSMUL +#undef BITSUNIT +#undef BITS + +#undef BRESSOLID +#undef BRESDASH +#undef DOTS +#undef ARC +#undef POLYLINE +#undef POLYSEGMENT + +#define BRESSOLID fbBresSolid32 +#define BRESDASH fbBresDash32 +#define DOTS fbDots32 +#define ARC fbArc32 +#define GLYPH fbGlyph32 +#define POLYLINE fbPolyline32 +#define POLYSEGMENT fbPolySegment32 +#define BITS CARD32 +#if FB_SHIFT == 6 +#define BITS2 FbBits +#endif + +#include "fbbits.h" + +#undef BRESSOLID +#undef BRESDASH +#undef DOTS +#undef ARC +#undef GLYPH +#undef POLYLINE +#undef POLYSEGMENT +#undef BITS +#if FB_SHIFT == 6 +#undef BITS2 +#endif diff --git a/fb/fbbits.h b/fb/fbbits.h new file mode 100644 index 0000000..c3bbf60 --- /dev/null +++ b/fb/fbbits.h @@ -0,0 +1,938 @@ +/* + * + * Copyright © 1998 Keith Packard + * + * 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, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD 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 file defines functions for drawing some primitives using + * underlying datatypes instead of masks + */ + +#define isClipped(c,ul,lr) ((((c) - (ul)) | ((lr) - (c))) & 0x80008000) + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#ifdef BITSMUL +#define MUL BITSMUL +#else +#define MUL 1 +#endif + +#ifdef BITSSTORE +#define STORE(b,x) BITSSTORE(b,x) +#else +#define STORE(b,x) (*(b) = (x)) +#endif + +#ifdef BITSRROP +#define RROP(b,a,x) BITSRROP(b,a,x) +#else +#define RROP(b,a,x) (*(b) = FbDoRRop (*(b), (a), (x))) +#endif + +#ifdef BITSUNIT +#define UNIT BITSUNIT +#define USE_SOLID +#else +#define UNIT BITS +#endif + +/* + * Define the following before including this file: + * + * BRESSOLID name of function for drawing a solid segment + * BRESDASH name of function for drawing a dashed segment + * DOTS name of function for drawing dots + * ARC name of function for drawing a solid arc + * BITS type of underlying unit + */ + +#ifdef BRESSOLID +void +BRESSOLID(DrawablePtr pDrawable, + GCPtr pGC, + int dashOffset, + int signdx, + int signdy, int axis, int x1, int y1, int e, int e1, int e3, int len) +{ + FbBits *dst; + + FbStride dstStride; + + int dstBpp; + + int dstXoff, dstYoff; + + FbGCPrivPtr pPriv = fbGetGCPrivate(pGC); + + UNIT *bits; + + FbStride bitsStride; + + FbStride majorStep, minorStep; + + BITS xor = (BITS) pPriv->xor; + + fbGetDrawable(pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); + bits = + ((UNIT *) (dst + ((y1 + dstYoff) * dstStride))) + (x1 + dstXoff) * MUL; + bitsStride = dstStride * (sizeof(FbBits) / sizeof(UNIT)); + if (signdy < 0) + bitsStride = -bitsStride; + if (axis == X_AXIS) { + majorStep = signdx * MUL; + minorStep = bitsStride; + } + else { + majorStep = bitsStride; + minorStep = signdx * MUL; + } + while (len--) { + STORE(bits, xor); + bits += majorStep; + e += e1; + if (e >= 0) { + bits += minorStep; + e += e3; + } + } +} +#endif + +#ifdef BRESDASH +void +BRESDASH(DrawablePtr pDrawable, + GCPtr pGC, + int dashOffset, + int signdx, + int signdy, int axis, int x1, int y1, int e, int e1, int e3, int len) +{ + FbBits *dst; + + FbStride dstStride; + + int dstBpp; + + int dstXoff, dstYoff; + + FbGCPrivPtr pPriv = fbGetGCPrivate(pGC); + + UNIT *bits; + + FbStride bitsStride; + + FbStride majorStep, minorStep; + + BITS xorfg, xorbg; + + FbDashDeclare; + int dashlen; + + Bool even; + + Bool doOdd; + + fbGetDrawable(pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); + doOdd = pGC->lineStyle == LineDoubleDash; + xorfg = (BITS) pPriv->xor; + xorbg = (BITS) pPriv->bgxor; + + FbDashInit(pGC, pPriv, dashOffset, dashlen, even); + + bits = + ((UNIT *) (dst + ((y1 + dstYoff) * dstStride))) + (x1 + dstXoff) * MUL; + bitsStride = dstStride * (sizeof(FbBits) / sizeof(UNIT)); + if (signdy < 0) + bitsStride = -bitsStride; + if (axis == X_AXIS) { + majorStep = signdx * MUL; + minorStep = bitsStride; + } + else { + majorStep = bitsStride; + minorStep = signdx * MUL; + } + if (dashlen >= len) + dashlen = len; + if (doOdd) { + if (!even) + goto doubleOdd; + for (;;) { + len -= dashlen; + while (dashlen--) { + STORE(bits, xorfg); + bits += majorStep; + if ((e += e1) >= 0) { + e += e3; + bits += minorStep; + } + } + if (!len) + break; + + FbDashNextEven(dashlen); + + if (dashlen >= len) + dashlen = len; + doubleOdd: + len -= dashlen; + while (dashlen--) { + STORE(bits, xorbg); + bits += majorStep; + if ((e += e1) >= 0) { + e += e3; + bits += minorStep; + } + } + if (!len) + break; + + FbDashNextOdd(dashlen); + + if (dashlen >= len) + dashlen = len; + } + } + else { + if (!even) + goto onOffOdd; + for (;;) { + len -= dashlen; + while (dashlen--) { + STORE(bits, xorfg); + bits += majorStep; + if ((e += e1) >= 0) { + e += e3; + bits += minorStep; + } + } + if (!len) + break; + + FbDashNextEven(dashlen); + + if (dashlen >= len) + dashlen = len; + onOffOdd: + len -= dashlen; + while (dashlen--) { + bits += majorStep; + if ((e += e1) >= 0) { + e += e3; + bits += minorStep; + } + } + if (!len) + break; + + FbDashNextOdd(dashlen); + + if (dashlen >= len) + dashlen = len; + } + } +} +#endif + +#ifdef DOTS +void +DOTS(FbBits * dst, + FbStride dstStride, + int dstBpp, + BoxPtr pBox, + xPoint * ptsOrig, + int npt, int xorg, int yorg, int xoff, int yoff, FbBits and, FbBits xor) +{ + INT32 *pts = (INT32 *) ptsOrig; + + UNIT *bits = (UNIT *) dst; + + UNIT *point; + + BITS bxor = (BITS) xor; + + BITS band = (BITS) and; + + FbStride bitsStride = dstStride * (sizeof(FbBits) / sizeof(UNIT)); + + INT32 ul, lr; + + INT32 pt; + + ul = coordToInt(pBox->x1 - xorg, pBox->y1 - yorg); + lr = coordToInt(pBox->x2 - xorg - 1, pBox->y2 - yorg - 1); + + bits += bitsStride * (yorg + yoff) + (xorg + xoff) * MUL; + + if (and == 0) { + while (npt--) { + pt = *pts++; + if (!isClipped(pt, ul, lr)) { + point = bits + intToY(pt) * bitsStride + intToX(pt) * MUL; + STORE(point, bxor); + } + } + } + else { + while (npt--) { + pt = *pts++; + if (!isClipped(pt, ul, lr)) { + point = bits + intToY(pt) * bitsStride + intToX(pt) * MUL; + RROP(point, band, bxor); + } + } + } +} +#endif + +#ifdef ARC + +#define ARCCOPY(d) STORE(d,xorBits) +#define ARCRROP(d) RROP(d,andBits,xorBits) + +void +ARC(FbBits * dst, + FbStride dstStride, + int dstBpp, xArc * arc, int drawX, int drawY, FbBits and, FbBits xor) +{ + UNIT *bits; + + FbStride bitsStride; + + miZeroArcRec info; + + Bool do360; + + int x; + + UNIT *yorgp, *yorgop; + + BITS andBits, xorBits; + + int yoffset, dyoffset; + + int y, a, b, d, mask; + + int k1, k3, dx, dy; + + bits = (UNIT *) dst; + bitsStride = dstStride * (sizeof(FbBits) / sizeof(UNIT)); + andBits = (BITS) and; + xorBits = (BITS) xor; + do360 = miZeroArcSetup(arc, &info, TRUE); + yorgp = bits + ((info.yorg + drawY) * bitsStride); + yorgop = bits + ((info.yorgo + drawY) * bitsStride); + info.xorg = (info.xorg + drawX) * MUL; + info.xorgo = (info.xorgo + drawX) * MUL; + MIARCSETUP(); + yoffset = y ? bitsStride : 0; + dyoffset = 0; + mask = info.initialMask; + + if (!(arc->width & 1)) { + if (andBits == 0) { + if (mask & 2) + ARCCOPY(yorgp + info.xorgo); + if (mask & 8) + ARCCOPY(yorgop + info.xorgo); + } + else { + if (mask & 2) + ARCRROP(yorgp + info.xorgo); + if (mask & 8) + ARCRROP(yorgop + info.xorgo); + } + } + if (!info.end.x || !info.end.y) { + mask = info.end.mask; + info.end = info.altend; + } + if (do360 && (arc->width == arc->height) && !(arc->width & 1)) { + int xoffset = bitsStride; + + UNIT *yorghb = yorgp + (info.h * bitsStride) + info.xorg; + + UNIT *yorgohb = yorghb - info.h * MUL; + + yorgp += info.xorg; + yorgop += info.xorg; + yorghb += info.h * MUL; + while (1) { + if (andBits == 0) { + ARCCOPY(yorgp + yoffset + x * MUL); + ARCCOPY(yorgp + yoffset - x * MUL); + ARCCOPY(yorgop - yoffset - x * MUL); + ARCCOPY(yorgop - yoffset + x * MUL); + } + else { + ARCRROP(yorgp + yoffset + x * MUL); + ARCRROP(yorgp + yoffset - x * MUL); + ARCRROP(yorgop - yoffset - x * MUL); + ARCRROP(yorgop - yoffset + x * MUL); + } + if (a < 0) + break; + if (andBits == 0) { + ARCCOPY(yorghb - xoffset - y * MUL); + ARCCOPY(yorgohb - xoffset + y * MUL); + ARCCOPY(yorgohb + xoffset + y * MUL); + ARCCOPY(yorghb + xoffset - y * MUL); + } + else { + ARCRROP(yorghb - xoffset - y * MUL); + ARCRROP(yorgohb - xoffset + y * MUL); + ARCRROP(yorgohb + xoffset + y * MUL); + ARCRROP(yorghb + xoffset - y * MUL); + } + xoffset += bitsStride; + MIARCCIRCLESTEP(yoffset += bitsStride; + ); + } + yorgp -= info.xorg; + yorgop -= info.xorg; + x = info.w; + yoffset = info.h * bitsStride; + } + else if (do360) { + while (y < info.h || x < info.w) { + MIARCOCTANTSHIFT(dyoffset = bitsStride; + ); + if (andBits == 0) { + ARCCOPY(yorgp + yoffset + info.xorg + x * MUL); + ARCCOPY(yorgp + yoffset + info.xorgo - x * MUL); + ARCCOPY(yorgop - yoffset + info.xorgo - x * MUL); + ARCCOPY(yorgop - yoffset + info.xorg + x * MUL); + } + else { + ARCRROP(yorgp + yoffset + info.xorg + x * MUL); + ARCRROP(yorgp + yoffset + info.xorgo - x * MUL); + ARCRROP(yorgop - yoffset + info.xorgo - x * MUL); + ARCRROP(yorgop - yoffset + info.xorg + x * MUL); + } + MIARCSTEP(yoffset += dyoffset; + , yoffset += bitsStride; + ); + } + } + else { + while (y < info.h || x < info.w) { + MIARCOCTANTSHIFT(dyoffset = bitsStride; + ); + if ((x == info.start.x) || (y == info.start.y)) { + mask = info.start.mask; + info.start = info.altstart; + } + if (andBits == 0) { + if (mask & 1) + ARCCOPY(yorgp + yoffset + info.xorg + x * MUL); + if (mask & 2) + ARCCOPY(yorgp + yoffset + info.xorgo - x * MUL); + if (mask & 4) + ARCCOPY(yorgop - yoffset + info.xorgo - x * MUL); + if (mask & 8) + ARCCOPY(yorgop - yoffset + info.xorg + x * MUL); + } + else { + if (mask & 1) + ARCRROP(yorgp + yoffset + info.xorg + x * MUL); + if (mask & 2) + ARCRROP(yorgp + yoffset + info.xorgo - x * MUL); + if (mask & 4) + ARCRROP(yorgop - yoffset + info.xorgo - x * MUL); + if (mask & 8) + ARCRROP(yorgop - yoffset + info.xorg + x * MUL); + } + if ((x == info.end.x) || (y == info.end.y)) { + mask = info.end.mask; + info.end = info.altend; + } + MIARCSTEP(yoffset += dyoffset; + , yoffset += bitsStride; + ); + } + } + if ((x == info.start.x) || (y == info.start.y)) + mask = info.start.mask; + if (andBits == 0) { + if (mask & 1) + ARCCOPY(yorgp + yoffset + info.xorg + x * MUL); + if (mask & 4) + ARCCOPY(yorgop - yoffset + info.xorgo - x * MUL); + if (arc->height & 1) { + if (mask & 2) + ARCCOPY(yorgp + yoffset + info.xorgo - x * MUL); + if (mask & 8) + ARCCOPY(yorgop - yoffset + info.xorg + x * MUL); + } + } + else { + if (mask & 1) + ARCRROP(yorgp + yoffset + info.xorg + x * MUL); + if (mask & 4) + ARCRROP(yorgop - yoffset + info.xorgo - x * MUL); + if (arc->height & 1) { + if (mask & 2) + ARCRROP(yorgp + yoffset + info.xorgo - x * MUL); + if (mask & 8) + ARCRROP(yorgop - yoffset + info.xorg + x * MUL); + } + } +} + +#undef ARCCOPY +#undef ARCRROP +#endif + +#ifdef GLYPH +#if BITMAP_BIT_ORDER == LSBFirst +# define WRITE_ADDR1(n) (n) +# define WRITE_ADDR2(n) (n) +# define WRITE_ADDR4(n) (n) +#else +# define WRITE_ADDR1(n) ((n) ^ 3) +# define WRITE_ADDR2(n) ((n) ^ 2) +# define WRITE_ADDR4(n) ((n)) +#endif + +#define WRITE1(d,n,fg) ((d)[WRITE_ADDR1(n)] = (BITS) (fg)) + +#ifdef BITS2 +# define WRITE2(d,n,fg) (*((BITS2 *) &((d)[WRITE_ADDR2(n)])) = (BITS2) (fg)) +#else +# define WRITE2(d,n,fg) WRITE1(d,(n)+1,WRITE1(d,n,fg)) +#endif + +#ifdef BITS4 +# define WRITE4(d,n,fg) (*((BITS4 *) &((d)[WRITE_ADDR4(n)])) = (BITS4) (fg)) +#else +# define WRITE4(d,n,fg) WRITE2(d,(n)+2,WRITE2(d,n,fg)) +#endif + +void +GLYPH(FbBits * dstBits, + FbStride dstStride, + int dstBpp, FbStip * stipple, FbBits fg, int x, int height) +{ + int lshift; + + FbStip bits; + + BITS *dstLine; + + BITS *dst; + + int n; + + int shift; + + dstLine = (BITS *) dstBits; + dstLine += x & ~3; + dstStride *= (sizeof(FbBits) / sizeof(BITS)); + shift = x & 3; + lshift = 4 - shift; + while (height--) { + bits = *stipple++; + dst = (BITS *) dstLine; + n = lshift; + while (bits) { + switch (FbStipMoveLsb(FbLeftStipBits(bits, n), 4, n)) { + case 0: + break; + case 1: + WRITE1(dst, 0, fg); + break; + case 2: + WRITE1(dst, 1, fg); + break; + case 3: + WRITE2(dst, 0, fg); + break; + case 4: + WRITE1(dst, 2, fg); + break; + case 5: + WRITE1(dst, 0, fg); + WRITE1(dst, 2, fg); + break; + case 6: + WRITE1(dst, 1, fg); + WRITE1(dst, 2, fg); + break; + case 7: + WRITE2(dst, 0, fg); + WRITE1(dst, 2, fg); + break; + case 8: + WRITE1(dst, 3, fg); + break; + case 9: + WRITE1(dst, 0, fg); + WRITE1(dst, 3, fg); + break; + case 10: + WRITE1(dst, 1, fg); + WRITE1(dst, 3, fg); + break; + case 11: + WRITE2(dst, 0, fg); + WRITE1(dst, 3, fg); + break; + case 12: + WRITE2(dst, 2, fg); + break; + case 13: + WRITE1(dst, 0, fg); + WRITE2(dst, 2, fg); + break; + case 14: + WRITE1(dst, 1, fg); + WRITE2(dst, 2, fg); + break; + case 15: + WRITE4(dst, 0, fg); + break; + } + bits = FbStipLeft(bits, n); + n = 4; + dst += 4; + } + dstLine += dstStride; + } +} + +#undef WRITE_ADDR1 +#undef WRITE_ADDR2 +#undef WRITE_ADDR4 +#undef WRITE1 +#undef WRITE2 +#undef WRITE4 + +#endif + +#ifdef POLYLINE +void +POLYLINE(DrawablePtr pDrawable, + GCPtr pGC, int mode, int npt, DDXPointPtr ptsOrig) +{ + INT32 *pts = (INT32 *) ptsOrig; + + int xoff = pDrawable->x; + + int yoff = pDrawable->y; + + unsigned int bias = miGetZeroLineBias(pDrawable->pScreen); + + BoxPtr pBox = REGION_EXTENTS(fbGetCompositeClip(pGC)); + + FbBits *dst; + + int dstStride; + + int dstBpp; + + int dstXoff, dstYoff; + + UNIT *bits, *bitsBase; + + FbStride bitsStride; + + BITS xor = fbGetGCPrivate(pGC)->xor; + + BITS and = fbGetGCPrivate(pGC)->and; + + int dashoffset = 0; + + INT32 ul, lr; + + INT32 pt1, pt2; + + int e, e1, e3, len; + + int stepmajor, stepminor; + + int octant; + + if (mode == CoordModePrevious) + fbFixCoordModePrevious(npt, ptsOrig); + + fbGetDrawable(pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); + bitsStride = dstStride * (sizeof(FbBits) / sizeof(UNIT)); + bitsBase = + ((UNIT *) dst) + (yoff + dstYoff) * bitsStride + (xoff + dstXoff) * MUL; + ul = coordToInt(pBox->x1 - xoff, pBox->y1 - yoff); + lr = coordToInt(pBox->x2 - xoff - 1, pBox->y2 - yoff - 1); + + pt1 = *pts++; + npt--; + pt2 = *pts++; + npt--; + for (;;) { + if (isClipped(pt1, ul, lr) | isClipped(pt2, ul, lr)) { + fbSegment(pDrawable, pGC, + intToX(pt1) + xoff, intToY(pt1) + yoff, + intToX(pt2) + xoff, intToY(pt2) + yoff, + npt == 0 && pGC->capStyle != CapNotLast, &dashoffset); + if (!npt) + return; + pt1 = pt2; + pt2 = *pts++; + npt--; + } + else { + bits = bitsBase + intToY(pt1) * bitsStride + intToX(pt1) * MUL; + for (;;) { + CalcLineDeltas(intToX(pt1), intToY(pt1), + intToX(pt2), intToY(pt2), + len, e1, stepmajor, stepminor, 1, bitsStride, + octant); + stepmajor *= MUL; + if (len < e1) { + e3 = len; + len = e1; + e1 = e3; + + e3 = stepminor; + stepminor = stepmajor; + stepmajor = e3; + SetYMajorOctant(octant); + } + e = -len; + e1 <<= 1; + e3 = e << 1; + FIXUP_ERROR(e, octant, bias); + if (and == 0) { + while (len--) { + STORE(bits, xor); + bits += stepmajor; + e += e1; + if (e >= 0) { + bits += stepminor; + e += e3; + } + } + } + else { + while (len--) { + RROP(bits, and, xor); + bits += stepmajor; + e += e1; + if (e >= 0) { + bits += stepminor; + e += e3; + } + } + } + if (!npt) { + if (pGC->capStyle != CapNotLast && + pt2 != *((INT32 *) ptsOrig)) { + RROP(bits, and, xor); + } + return; + } + pt1 = pt2; + pt2 = *pts++; + --npt; + if (isClipped(pt2, ul, lr)) + break; + } + } + } +} +#endif + +#ifdef POLYSEGMENT +void +POLYSEGMENT(DrawablePtr pDrawable, GCPtr pGC, int nseg, xSegment * pseg) +{ + INT32 *pts = (INT32 *) pseg; + + int xoff = pDrawable->x; + + int yoff = pDrawable->y; + + unsigned int bias = miGetZeroLineBias(pDrawable->pScreen); + + BoxPtr pBox = REGION_EXTENTS(fbGetCompositeClip(pGC)); + + FbBits *dst; + + int dstStride; + + int dstBpp; + + int dstXoff, dstYoff; + + UNIT *bits, *bitsBase; + + FbStride bitsStride; + + FbBits xorBits = fbGetGCPrivate(pGC)->xor; + + FbBits andBits = fbGetGCPrivate(pGC)->and; + + BITS xor = xorBits; + + BITS and = andBits; + + int dashoffset = 0; + + INT32 ul, lr; + + INT32 pt1, pt2; + + int e, e1, e3, len; + + int stepmajor, stepminor; + + int octant; + + Bool capNotLast; + + fbGetDrawable(pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); + bitsStride = dstStride * (sizeof(FbBits) / sizeof(UNIT)); + bitsBase = + ((UNIT *) dst) + (yoff + dstYoff) * bitsStride + (xoff + dstXoff) * MUL; + ul = coordToInt(pBox->x1 - xoff, pBox->y1 - yoff); + lr = coordToInt(pBox->x2 - xoff - 1, pBox->y2 - yoff - 1); + + capNotLast = pGC->capStyle == CapNotLast; + + while (nseg--) { + pt1 = *pts++; + pt2 = *pts++; + if (isClipped(pt1, ul, lr) | isClipped(pt2, ul, lr)) { + fbSegment(pDrawable, pGC, + intToX(pt1) + xoff, intToY(pt1) + yoff, + intToX(pt2) + xoff, intToY(pt2) + yoff, + !capNotLast, &dashoffset); + } + else { + CalcLineDeltas(intToX(pt1), intToY(pt1), + intToX(pt2), intToY(pt2), + len, e1, stepmajor, stepminor, 1, bitsStride, + octant); + if (e1 == 0 && len > 3 +#if MUL != 1 + && FbCheck24Pix(and) && FbCheck24Pix(xor) +#endif + ) { + int x1, x2; + + FbBits *dstLine; + + int dstX, width; + + FbBits startmask, endmask; + + int nmiddle; + + if (stepmajor < 0) { + x1 = intToX(pt2); + x2 = intToX(pt1) + 1; + if (capNotLast) + x1++; + } + else { + x1 = intToX(pt1); + x2 = intToX(pt2); + if (!capNotLast) + x2++; + } + dstX = (x1 + xoff + dstXoff) * (sizeof(UNIT) * 8 * MUL); + width = (x2 - x1) * (sizeof(UNIT) * 8 * MUL); + + dstLine = dst + (intToY(pt1) + yoff + dstYoff) * dstStride; + dstLine += dstX >> FB_SHIFT; + dstX &= FB_MASK; + FbMaskBits(dstX, width, startmask, nmiddle, endmask); + if (startmask) { + *dstLine = + FbDoMaskRRop(*dstLine, andBits, xorBits, startmask); + dstLine++; + } + if (!andBits) + while (nmiddle--) + *dstLine++ = xorBits; + else + while (nmiddle--) { + *dstLine = FbDoRRop(*dstLine, andBits, xorBits); + dstLine++; + } + if (endmask) + *dstLine = + FbDoMaskRRop(*dstLine, andBits, xorBits, endmask); + } + else { + stepmajor *= MUL; + bits = bitsBase + intToY(pt1) * bitsStride + intToX(pt1) * MUL; + if (len < e1) { + e3 = len; + len = e1; + e1 = e3; + + e3 = stepminor; + stepminor = stepmajor; + stepmajor = e3; + SetYMajorOctant(octant); + } + e = -len; + e1 <<= 1; + e3 = e << 1; + FIXUP_ERROR(e, octant, bias); + if (!capNotLast) + len++; + if (and == 0) { + while (len--) { + STORE(bits, xor); + bits += stepmajor; + e += e1; + if (e >= 0) { + bits += stepminor; + e += e3; + } + } + } + else { + while (len--) { + RROP(bits, and, xor); + bits += stepmajor; + e += e1; + if (e >= 0) { + bits += stepminor; + e += e3; + } + } + } + } + } + } +} +#endif + +#undef MUL +#undef STORE +#undef RROP +#undef UNIT +#undef USE_SOLID + +#undef isClipped diff --git a/fb/fbblt.c b/fb/fbblt.c new file mode 100644 index 0000000..7c07d36 --- /dev/null +++ b/fb/fbblt.c @@ -0,0 +1,818 @@ +/* + * + * Copyright © 1998 Keith Packard + * + * 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, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#include "fb.h" + +#define InitializeShifts(sx,dx,ls,rs) { \ + if (sx != dx) { \ + if (sx > dx) { \ + ls = sx - dx; \ + rs = FB_UNIT - ls; \ + } else { \ + rs = dx - sx; \ + ls = FB_UNIT - rs; \ + } \ + } \ +} + +void +fbBlt(FbBits * srcLine, + FbStride srcStride, + int srcX, + FbBits * dstLine, + FbStride dstStride, + int dstX, + int width, + int height, int alu, FbBits pm, int bpp, Bool reverse, Bool upsidedown) +{ + FbBits *src, *dst; + int leftShift, rightShift; + FbBits startmask, endmask; + FbBits bits, bits1; + int n, nmiddle; + Bool destInvarient; + int careful; + int startbyte, endbyte; + + FbDeclareMergeRop(); + + if (bpp == 24 && !FbCheck24Pix(pm)) { + fbBlt24(srcLine, srcStride, srcX, dstLine, dstStride, dstX, + width, height, alu, pm, reverse, upsidedown); + return; + } + + careful = !((srcLine < dstLine && srcLine + width * (bpp>>3) > dstLine) || + (dstLine < srcLine && dstLine + width * (bpp>>3) > srcLine)) || + (bpp & 7); + + if (alu == GXcopy && pm == FB_ALLONES && !careful && + !(srcX & 7) && !(dstX & 7) && !(width & 7)) { + int i; + CARD8 *tmpsrc = (CARD8 *) srcLine; + CARD8 *tmpdst = (CARD8 *) dstLine; + + srcStride *= sizeof(FbBits); + dstStride *= sizeof(FbBits); + width >>= 3; + tmpsrc += (srcX >> 3); + tmpdst += (dstX >> 3); + + if (!upsidedown) + for (i = 0; i < height; i++) + memcpy(tmpdst + i * dstStride, tmpsrc + i * srcStride, width); + else + for (i = height - 1; i >= 0; i--) + memcpy(tmpdst + i * dstStride, tmpsrc + i * srcStride, width); + + return; + } + + FbInitializeMergeRop(alu, pm); + destInvarient = FbDestInvarientMergeRop(); + if (upsidedown) { + srcLine += (height - 1) * (srcStride); + dstLine += (height - 1) * (dstStride); + srcStride = -srcStride; + dstStride = -dstStride; + } + FbMaskBitsBytes(dstX, width, destInvarient, startmask, startbyte, + nmiddle, endmask, endbyte); + if (reverse) { + srcLine += ((srcX + width - 1) >> FB_SHIFT) + 1; + dstLine += ((dstX + width - 1) >> FB_SHIFT) + 1; + srcX = (srcX + width - 1) & FB_MASK; + dstX = (dstX + width - 1) & FB_MASK; + } + else { + srcLine += srcX >> FB_SHIFT; + dstLine += dstX >> FB_SHIFT; + srcX &= FB_MASK; + dstX &= FB_MASK; + } + if (srcX == dstX) { + while (height--) { + src = srcLine; + srcLine += srcStride; + dst = dstLine; + dstLine += dstStride; + if (reverse) { + if (endmask) { + bits = *--src; + --dst; + FbDoRightMaskByteMergeRop(dst, bits, endbyte, endmask); + } + n = nmiddle; + if (destInvarient) { + while (n--) + *--dst = FbDoDestInvarientMergeRop(*--src); + } + else { + while (n--) { + bits = *--src; + --dst; + *dst = FbDoMergeRop(bits, *dst); + } + } + if (startmask) { + bits = *--src; + --dst; + FbDoLeftMaskByteMergeRop(dst, bits, startbyte, startmask); + } + } + else { + if (startmask) { + bits = *src++; + FbDoLeftMaskByteMergeRop(dst, bits, startbyte, startmask); + dst++; + } + n = nmiddle; + if (destInvarient) { +#if 0 + /* + * This provides some speedup on screen->screen blts + * over the PCI bus, usually about 10%. But fb + * isn't usually used for this operation... + */ + if (_ca2 + 1 == 0 && _cx2 == 0) { + FbBits t1, t2, t3, t4; + + while (n >= 4) { + t1 = *src++; + t2 = *src++; + t3 = *src++; + t4 = *src++; + *dst++ = t1; + *dst++ = t2; + *dst++ = t3; + *dst++ = t4; + n -= 4; + } + } +#endif + while (n--) + *dst++ = FbDoDestInvarientMergeRop(*src++); + } + else { + while (n--) { + bits = *src++; + *dst = FbDoMergeRop(bits, *dst); + dst++; + } + } + if (endmask) { + bits = *src; + FbDoRightMaskByteMergeRop(dst, bits, endbyte, endmask); + } + } + } + } + else { + if (srcX > dstX) { + leftShift = srcX - dstX; + rightShift = FB_UNIT - leftShift; + } + else { + rightShift = dstX - srcX; + leftShift = FB_UNIT - rightShift; + } + while (height--) { + src = srcLine; + srcLine += srcStride; + dst = dstLine; + dstLine += dstStride; + + bits1 = 0; + if (reverse) { + if (srcX < dstX) + bits1 = *--src; + if (endmask) { + bits = FbScrRight(bits1, rightShift); + if (FbScrRight(endmask, leftShift)) { + bits1 = *--src; + bits |= FbScrLeft(bits1, leftShift); + } + --dst; + FbDoRightMaskByteMergeRop(dst, bits, endbyte, endmask); + } + n = nmiddle; + if (destInvarient) { + while (n--) { + bits = FbScrRight(bits1, rightShift); + bits1 = *--src; + bits |= FbScrLeft(bits1, leftShift); + --dst; + *dst = FbDoDestInvarientMergeRop(bits); + } + } + else { + while (n--) { + bits = FbScrRight(bits1, rightShift); + bits1 = *--src; + bits |= FbScrLeft(bits1, leftShift); + --dst; + *dst = FbDoMergeRop(bits, *dst); + } + } + if (startmask) { + bits = FbScrRight(bits1, rightShift); + if (FbScrRight(startmask, leftShift)) { + bits1 = *--src; + bits |= FbScrLeft(bits1, leftShift); + } + --dst; + FbDoLeftMaskByteMergeRop(dst, bits, startbyte, startmask); + } + } + else { + if (srcX > dstX) + bits1 = *src++; + if (startmask) { + bits = FbScrLeft(bits1, leftShift); + if (FbScrLeft(startmask, rightShift)) { + bits1 = *src++; + bits |= FbScrRight(bits1, rightShift); + } + FbDoLeftMaskByteMergeRop(dst, bits, startbyte, startmask); + dst++; + } + n = nmiddle; + if (destInvarient) { + while (n--) { + bits = FbScrLeft(bits1, leftShift); + bits1 = *src++; + bits |= FbScrRight(bits1, rightShift); + *dst = FbDoDestInvarientMergeRop(bits); + dst++; + } + } + else { + while (n--) { + bits = FbScrLeft(bits1, leftShift); + bits1 = *src++; + bits |= FbScrRight(bits1, rightShift); + *dst = FbDoMergeRop(bits, *dst); + dst++; + } + } + if (endmask) { + bits = FbScrLeft(bits1, leftShift); + if (FbScrLeft(endmask, rightShift)) { + bits1 = *src; + bits |= FbScrRight(bits1, rightShift); + } + FbDoRightMaskByteMergeRop(dst, bits, endbyte, endmask); + } + } + } + } +} + + +#undef DEBUG_BLT24 +#ifdef DEBUG_BLT24 + +static unsigned long +getPixel(char *src, int x) +{ + unsigned long l; + + l = 0; + memcpy(&l, src + x * 3, 3); + return l; +} +#endif + +static void +fbBlt24Line(FbBits * src, + int srcX, + FbBits * dst, int dstX, int width, int alu, FbBits pm, Bool reverse) +{ +#ifdef DEBUG_BLT24 + char *origDst = (char *) dst; + + FbBits *origLine = dst + ((dstX >> FB_SHIFT) - 1); + + int origNlw = ((width + FB_MASK) >> FB_SHIFT) + 3; + + int origX = dstX / 24; +#endif + + int leftShift, rightShift; + + FbBits startmask, endmask; + + int n; + + FbBits bits, bits1; + + FbBits mask; + + int rot; + + FbDeclareMergeRop(); + + FbInitializeMergeRop(alu, FB_ALLONES); + FbMaskBits(dstX, width, startmask, n, endmask); +#ifdef DEBUG_BLT24 + ErrorF("dstX %d width %d reverse %d\n", dstX, width, reverse); +#endif + if (reverse) { + src += ((srcX + width - 1) >> FB_SHIFT) + 1; + dst += ((dstX + width - 1) >> FB_SHIFT) + 1; + rot = FbFirst24Rot(((dstX + width - 8) & FB_MASK)); + rot = FbPrev24Rot(rot); +#ifdef DEBUG_BLT24 + ErrorF("dstX + width - 8: %d rot: %d\n", (dstX + width - 8) & FB_MASK, + rot); +#endif + srcX = (srcX + width - 1) & FB_MASK; + dstX = (dstX + width - 1) & FB_MASK; + } + else { + src += srcX >> FB_SHIFT; + dst += dstX >> FB_SHIFT; + srcX &= FB_MASK; + dstX &= FB_MASK; + rot = FbFirst24Rot(dstX); +#ifdef DEBUG_BLT24 + ErrorF("dstX: %d rot: %d\n", dstX, rot); +#endif + } + mask = FbRot24(pm, rot); +#ifdef DEBUG_BLT24 + ErrorF("pm 0x%x mask 0x%x\n", pm, mask); +#endif + if (srcX == dstX) { + if (reverse) { + if (endmask) { + bits = *--src; + --dst; + *dst = FbDoMaskMergeRop(bits, *dst, mask & endmask); + mask = FbPrev24Pix(mask); + } + while (n--) { + bits = *--src; + --dst; + *dst = FbDoMaskMergeRop(bits, *dst, mask); + mask = FbPrev24Pix(mask); + } + if (startmask) { + bits = *--src; + --dst; + *dst = FbDoMaskMergeRop(bits, *dst, mask & startmask); + } + } + else { + if (startmask) { + bits = *src++; + *dst = FbDoMaskMergeRop(bits, *dst, mask & startmask); + dst++; + mask = FbNext24Pix(mask); + } + while (n--) { + bits = *src++; + *dst = FbDoMaskMergeRop(bits, *dst, mask); + dst++; + mask = FbNext24Pix(mask); + } + if (endmask) { + bits = *src; + *dst = FbDoMaskMergeRop(bits, *dst, mask & endmask); + } + } + } + else { + if (srcX > dstX) { + leftShift = srcX - dstX; + rightShift = FB_UNIT - leftShift; + } + else { + rightShift = dstX - srcX; + leftShift = FB_UNIT - rightShift; + } + + bits1 = 0; + if (reverse) { + if (srcX < dstX) + bits1 = *--src; + if (endmask) { + bits = FbScrRight(bits1, rightShift); + if (FbScrRight(endmask, leftShift)) { + bits1 = *--src; + bits |= FbScrLeft(bits1, leftShift); + } + --dst; + *dst = FbDoMaskMergeRop(bits, *dst, mask & endmask); + mask = FbPrev24Pix(mask); + } + while (n--) { + bits = FbScrRight(bits1, rightShift); + bits1 = *--src; + bits |= FbScrLeft(bits1, leftShift); + --dst; + *dst = FbDoMaskMergeRop(bits, *dst, mask); + mask = FbPrev24Pix(mask); + } + if (startmask) { + bits = FbScrRight(bits1, rightShift); + if (FbScrRight(startmask, leftShift)) { + bits1 = *--src; + bits |= FbScrLeft(bits1, leftShift); + } + --dst; + *dst = FbDoMaskMergeRop(bits, *dst, mask & startmask); + } + } + else { + if (srcX > dstX) + bits1 = *src++; + if (startmask) { + bits = FbScrLeft(bits1, leftShift); + bits1 = *src++; + bits |= FbScrRight(bits1, rightShift); + *dst = FbDoMaskMergeRop(bits, *dst, mask & startmask); + dst++; + mask = FbNext24Pix(mask); + } + while (n--) { + bits = FbScrLeft(bits1, leftShift); + bits1 = *src++; + bits |= FbScrRight(bits1, rightShift); + *dst = FbDoMaskMergeRop(bits, *dst, mask); + dst++; + mask = FbNext24Pix(mask); + } + if (endmask) { + bits = FbScrLeft(bits1, leftShift); + if (FbScrLeft(endmask, rightShift)) { + bits1 = *src; + bits |= FbScrRight(bits1, rightShift); + } + *dst = FbDoMaskMergeRop(bits, *dst, mask & endmask); + } + } + } +#ifdef DEBUG_BLT24 + { + int firstx, lastx, x; + + firstx = origX; + if (firstx) + firstx--; + lastx = origX + width / 24 + 1; + for (x = firstx; x <= lastx; x++) + ErrorF("%06x ", getPixel(origDst, x)); + ErrorF("\n"); + while (origNlw--) + ErrorF("%08x ", *origLine++); + ErrorF("\n"); + } +#endif +} + +void +fbBlt24(FbBits * srcLine, + FbStride srcStride, + int srcX, + FbBits * dstLine, + FbStride dstStride, + int dstX, + int width, + int height, int alu, FbBits pm, Bool reverse, Bool upsidedown) +{ + if (upsidedown) { + srcLine += (height - 1) * srcStride; + dstLine += (height - 1) * dstStride; + srcStride = -srcStride; + dstStride = -dstStride; + } + while (height--) { + fbBlt24Line(srcLine, srcX, dstLine, dstX, width, alu, pm, reverse); + srcLine += srcStride; + dstLine += dstStride; + } +#ifdef DEBUG_BLT24 + ErrorF("\n"); +#endif +} + +#if FB_SHIFT == FB_STIP_SHIFT + 1 + +/* + * Could be generalized to FB_SHIFT > FB_STIP_SHIFT + 1 by + * creating an ring of values stepped through for each line + */ + +void +fbBltOdd(FbBits * srcLine, + FbStride srcStrideEven, + FbStride srcStrideOdd, + int srcXEven, + int srcXOdd, + FbBits * dstLine, + FbStride dstStrideEven, + FbStride dstStrideOdd, + int dstXEven, + int dstXOdd, int width, int height, int alu, FbBits pm, int bpp) +{ + FbBits *src; + + int leftShiftEven, rightShiftEven; + + FbBits startmaskEven, endmaskEven; + + int nmiddleEven; + + FbBits *dst; + + int leftShiftOdd, rightShiftOdd; + + FbBits startmaskOdd, endmaskOdd; + + int nmiddleOdd; + + int leftShift, rightShift; + + FbBits startmask, endmask; + + int nmiddle; + + int srcX, dstX; + + FbBits bits, bits1; + + int n; + + Bool destInvarient; + + Bool even; + + FbDeclareMergeRop(); + + FbInitializeMergeRop(alu, pm); + destInvarient = FbDestInvarientMergeRop(); + + srcLine += srcXEven >> FB_SHIFT; + dstLine += dstXEven >> FB_SHIFT; + srcXEven &= FB_MASK; + dstXEven &= FB_MASK; + srcXOdd &= FB_MASK; + dstXOdd &= FB_MASK; + + FbMaskBits(dstXEven, width, startmaskEven, nmiddleEven, endmaskEven); + FbMaskBits(dstXOdd, width, startmaskOdd, nmiddleOdd, endmaskOdd); + + even = TRUE; + InitializeShifts(srcXEven, dstXEven, leftShiftEven, rightShiftEven); + InitializeShifts(srcXOdd, dstXOdd, leftShiftOdd, rightShiftOdd); + while (height--) { + src = srcLine; + dst = dstLine; + if (even) { + srcX = srcXEven; + dstX = dstXEven; + startmask = startmaskEven; + endmask = endmaskEven; + nmiddle = nmiddleEven; + leftShift = leftShiftEven; + rightShift = rightShiftEven; + srcLine += srcStrideEven; + dstLine += dstStrideEven; + even = FALSE; + } + else { + srcX = srcXOdd; + dstX = dstXOdd; + startmask = startmaskOdd; + endmask = endmaskOdd; + nmiddle = nmiddleOdd; + leftShift = leftShiftOdd; + rightShift = rightShiftOdd; + srcLine += srcStrideOdd; + dstLine += dstStrideOdd; + even = TRUE; + } + if (srcX == dstX) { + if (startmask) { + bits = *src++; + *dst = FbDoMaskMergeRop(bits, *dst, startmask); + dst++; + } + n = nmiddle; + if (destInvarient) { + while (n--) { + bits = *src++; + *dst = FbDoDestInvarientMergeRop(bits); + dst++; + } + } + else { + while (n--) { + bits = *src++; + *dst = FbDoMergeRop(bits, *dst); + dst++; + } + } + if (endmask) { + bits = *src; + *dst = FbDoMaskMergeRop(bits, *dst, endmask); + } + } + else { + bits = 0; + if (srcX > dstX) + bits = *src++; + if (startmask) { + bits1 = FbScrLeft(bits, leftShift); + bits = *src++; + bits1 |= FbScrRight(bits, rightShift); + *dst = FbDoMaskMergeRop(bits1, *dst, startmask); + dst++; + } + n = nmiddle; + if (destInvarient) { + while (n--) { + bits1 = FbScrLeft(bits, leftShift); + bits = *src++; + bits1 |= FbScrRight(bits, rightShift); + *dst = FbDoDestInvarientMergeRop(bits1); + dst++; + } + } + else { + while (n--) { + bits1 = FbScrLeft(bits, leftShift); + bits = *src++; + bits1 |= FbScrRight(bits, rightShift); + *dst = FbDoMergeRop(bits1, *dst); + dst++; + } + } + if (endmask) { + bits1 = FbScrLeft(bits, leftShift); + if (FbScrLeft(endmask, rightShift)) { + bits = *src; + bits1 |= FbScrRight(bits, rightShift); + } + *dst = FbDoMaskMergeRop(bits1, *dst, endmask); + } + } + } +} + +void +fbBltOdd24(FbBits * srcLine, + FbStride srcStrideEven, + FbStride srcStrideOdd, + int srcXEven, + int srcXOdd, + FbBits * dstLine, + FbStride dstStrideEven, + FbStride dstStrideOdd, + int dstXEven, int dstXOdd, int width, int height, int alu, FbBits pm) +{ + Bool even = TRUE; + + while (height--) { + if (even) { + fbBlt24Line(srcLine, srcXEven, dstLine, dstXEven, + width, alu, pm, FALSE); + srcLine += srcStrideEven; + dstLine += dstStrideEven; + even = FALSE; + } + else { + fbBlt24Line(srcLine, srcXOdd, dstLine, dstXOdd, + width, alu, pm, FALSE); + srcLine += srcStrideOdd; + dstLine += dstStrideOdd; + even = TRUE; + } + } +#if 0 + fprintf(stderr, "\n"); +#endif +} + +#endif + +#if FB_STIP_SHIFT != FB_SHIFT +void +fbSetBltOdd(FbStip * stip, + FbStride stipStride, + int srcX, + FbBits ** bits, + FbStride * strideEven, + FbStride * strideOdd, int *srcXEven, int *srcXOdd) +{ + int srcAdjust; + + int strideAdjust; + + /* + * bytes needed to align source + */ + srcAdjust = (((int) stip) & (FB_MASK >> 3)); + /* + * FbStip units needed to align stride + */ + strideAdjust = stipStride & (FB_MASK >> FB_STIP_SHIFT); + + *bits = (FbBits *) ((char *) stip - srcAdjust); + if (srcAdjust) { + *strideEven = FbStipStrideToBitsStride(stipStride + 1); + *strideOdd = FbStipStrideToBitsStride(stipStride); + + *srcXEven = srcX + (srcAdjust << 3); + *srcXOdd = srcX + (srcAdjust << 3) - (strideAdjust << FB_STIP_SHIFT); + } + else { + *strideEven = FbStipStrideToBitsStride(stipStride); + *strideOdd = FbStipStrideToBitsStride(stipStride + 1); + + *srcXEven = srcX; + *srcXOdd = srcX + (strideAdjust << FB_STIP_SHIFT); + } +} +#endif + +void +fbBltStip(FbStip * src, FbStride srcStride, /* in FbStip units, not FbBits units */ + int srcX, FbStip * dst, FbStride dstStride, /* in FbStip units, not FbBits units */ + int dstX, int width, int height, int alu, FbBits pm, int bpp) +{ +#if FB_STIP_SHIFT != FB_SHIFT + if (FB_STIP_ODDSTRIDE(srcStride) || FB_STIP_ODDPTR(src) || + FB_STIP_ODDSTRIDE(dstStride) || FB_STIP_ODDPTR(dst)) { + FbStride srcStrideEven, srcStrideOdd; + + FbStride dstStrideEven, dstStrideOdd; + + int srcXEven, srcXOdd; + + int dstXEven, dstXOdd; + + FbBits *s, *d; + + int sx, dx; + + src += srcX >> FB_STIP_SHIFT; + srcX &= FB_STIP_MASK; + dst += dstX >> FB_STIP_SHIFT; + dstX &= FB_STIP_MASK; + + fbSetBltOdd(src, srcStride, srcX, + &s, &srcStrideEven, &srcStrideOdd, &srcXEven, &srcXOdd); + + fbSetBltOdd(dst, dstStride, dstX, + &d, &dstStrideEven, &dstStrideOdd, &dstXEven, &dstXOdd); + + if (bpp == 24 && !FbCheck24Pix(pm)) { + fbBltOdd24(s, srcStrideEven, srcStrideOdd, + srcXEven, srcXOdd, + d, dstStrideEven, dstStrideOdd, + dstXEven, dstXOdd, width, height, alu, pm); + } + else + { + fbBltOdd(s, srcStrideEven, srcStrideOdd, + srcXEven, srcXOdd, + d, dstStrideEven, dstStrideOdd, + dstXEven, dstXOdd, width, height, alu, pm, bpp); + } + } + else +#endif + { + fbBlt((FbBits *) src, FbStipStrideToBitsStride(srcStride), + srcX, + (FbBits *) dst, FbStipStrideToBitsStride(dstStride), + dstX, width, height, alu, pm, bpp, FALSE, FALSE); + } +} diff --git a/fb/fbbltone.c b/fb/fbbltone.c new file mode 100644 index 0000000..55f01ea --- /dev/null +++ b/fb/fbbltone.c @@ -0,0 +1,840 @@ +/* + * + * Copyright © 1998 Keith Packard + * + * 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, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "fb.h" + +/* + * Example: srcX = 13 dstX = 8 (FB unit 32 dstBpp 8) + * + * **** **** **** **** **** **** **** **** + * ^ + * ******** ******** ******** ******** + * ^ + * leftShift = 12 + * rightShift = 20 + * + * Example: srcX = 0 dstX = 8 (FB unit 32 dstBpp 8) + * + * **** **** **** **** **** **** **** **** + * ^ + * ******** ******** ******** ******** + * ^ + * + * leftShift = 24 + * rightShift = 8 + */ + +#define LoadBits {\ + if (leftShift) { \ + bitsRight = (src < srcEnd ? *src++ : 0); \ + bits = (FbStipLeft (bitsLeft, leftShift) | \ + FbStipRight(bitsRight, rightShift)); \ + bitsLeft = bitsRight; \ + } else \ + bits = (src < srcEnd ? *src++ : 0); \ +} + + +#define LaneCases1(n,a) case n: (void)FbLaneCase(n,a); break +#define LaneCases2(n,a) LaneCases1(n,a); LaneCases1(n+1,a) +#define LaneCases4(n,a) LaneCases2(n,a); LaneCases2(n+2,a) +#define LaneCases8(n,a) LaneCases4(n,a); LaneCases4(n+4,a) +#define LaneCases16(n,a) LaneCases8(n,a); LaneCases8(n+8,a) +#define LaneCases32(n,a) LaneCases16(n,a); LaneCases16(n+16,a) +#define LaneCases64(n,a) LaneCases32(n,a); LaneCases32(n+32,a) +#define LaneCases128(n,a) LaneCases64(n,a); LaneCases64(n+64,a) +#define LaneCases256(n,a) LaneCases128(n,a); LaneCases128(n+128,a) + +#if FB_SHIFT == 6 +#define LaneCases(a) LaneCases256(0,a) +#endif + +#if FB_SHIFT == 5 +#define LaneCases(a) LaneCases16(0,a) +#endif + +#if FB_SHIFT == 6 +static const CARD8 fb8Lane[256] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, + 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, + 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, + 113, 114, 115, + 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, + 131, 132, 133, + 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, + 149, 150, 151, + 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, + 167, 168, 169, + 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, + 185, 186, 187, + 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, + 203, 204, 205, + 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, + 221, 222, 223, + 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, + 239, 240, 241, + 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, +}; + +static const CARD8 fb16Lane[256] = { + 0x00, 0x03, 0x0c, 0x0f, + 0x30, 0x33, 0x3c, 0x3f, + 0xc0, 0xc3, 0xcc, 0xcf, + 0xf0, 0xf3, 0xfc, 0xff, +}; + +static const CARD8 fb32Lane[16] = { + 0x00, 0x0f, 0xf0, 0xff, +}; +#endif + +#if FB_SHIFT == 5 +static const CARD8 fb8Lane[16] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 +}; + +static const CARD8 fb16Lane[16] = { + 0, 3, 12, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const CARD8 fb32Lane[16] = { + 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; +#endif + +static const CARD8 * const fbLaneTable[33] = { + 0, 0, 0, 0, 0, 0, 0, 0, + fb8Lane, 0, 0, 0, 0, 0, 0, 0, + fb16Lane, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + fb32Lane +}; + +void +fbBltOne(FbStip * src, FbStride srcStride, /* FbStip units per scanline */ + int srcX, /* bit position of source */ + FbBits * dst, FbStride dstStride, /* FbBits units per scanline */ + int dstX, /* bit position of dest */ + int dstBpp, /* bits per destination unit */ + int width, /* width in bits of destination */ + int height, /* height in scanlines */ + FbBits fgand, /* rrop values */ + FbBits fgxor, FbBits bgand, FbBits bgxor) +{ + const FbBits *fbBits; + + FbBits *srcEnd; + + int pixelsPerDst; /* dst pixels per FbBits */ + + int unitsPerSrc; /* src patterns per FbStip */ + + int leftShift, rightShift; /* align source with dest */ + + FbBits startmask, endmask; /* dest scanline masks */ + + FbStip bits = 0, bitsLeft, bitsRight; /* source bits */ + + FbStip left; + + FbBits mask; + + int nDst; /* dest longwords (w.o. end) */ + + int w; + + int n, nmiddle; + + int dstS; /* stipple-relative dst X coordinate */ + + Bool copy; /* accelerate dest-invariant */ + + Bool transparent; /* accelerate 0 nop */ + + int srcinc; /* source units consumed */ + + Bool endNeedsLoad = FALSE; /* need load for endmask */ + + const CARD8 *fbLane; + int startbyte, endbyte; + + if (dstBpp == 24) { + fbBltOne24(src, srcStride, srcX, + dst, dstStride, dstX, dstBpp, + width, height, fgand, fgxor, bgand, bgxor); + return; + } + + /* + * Do not read past the end of the buffer! + */ + srcEnd = src + height * srcStride; + + /* + * Number of destination units in FbBits == number of stipple pixels + * used each time + */ + pixelsPerDst = FB_UNIT / dstBpp; + + /* + * Number of source stipple patterns in FbStip + */ + unitsPerSrc = FB_STIP_UNIT / pixelsPerDst; + + copy = FALSE; + transparent = FALSE; + if (bgand == 0 && fgand == 0) + copy = TRUE; + else if (bgand == FB_ALLONES && bgxor == 0) + transparent = TRUE; + + /* + * Adjust source and dest to nearest FbBits boundary + */ + src += srcX >> FB_STIP_SHIFT; + dst += dstX >> FB_SHIFT; + srcX &= FB_STIP_MASK; + dstX &= FB_MASK; + + FbMaskBitsBytes(dstX, width, copy, + startmask, startbyte, nmiddle, endmask, endbyte); + + /* + * Compute effective dest alignment requirement for + * source -- must align source to dest unit boundary + */ + dstS = dstX / dstBpp; + /* + * Compute shift constants for effective alignement + */ + if (srcX >= dstS) { + leftShift = srcX - dstS; + rightShift = FB_STIP_UNIT - leftShift; + } + else { + rightShift = dstS - srcX; + leftShift = FB_STIP_UNIT - rightShift; + } + /* + * Get pointer to stipple mask array for this depth + */ + fbBits = 0; /* unused */ + if (pixelsPerDst <= 8) + fbBits = fbStippleTable[pixelsPerDst]; + fbLane = 0; + if (transparent && fgand == 0 && dstBpp >= 8) + fbLane = fbLaneTable[dstBpp]; + + /* + * Compute total number of destination words written, but + * don't count endmask + */ + nDst = nmiddle; + if (startmask) + nDst++; + + dstStride -= nDst; + + /* + * Compute total number of source words consumed + */ + + srcinc = (nDst + unitsPerSrc - 1) / unitsPerSrc; + + if (srcX > dstS) + srcinc++; + if (endmask) { + endNeedsLoad = nDst % unitsPerSrc == 0; + if (endNeedsLoad) + srcinc++; + } + + srcStride -= srcinc; + + /* + * Copy rectangle + */ + while (height--) { + w = nDst; /* total units across scanline */ + n = unitsPerSrc; /* units avail in single stipple */ + if (n > w) + n = w; + + bitsLeft = 0; + if (srcX > dstS) + bitsLeft = *src++; + if (n) { + /* + * Load first set of stipple bits + */ + LoadBits; + + /* + * Consume stipple bits for startmask + */ + if (startmask) { +#if FB_UNIT > 32 + if (pixelsPerDst == 16) + mask = FbStipple16Bits(FbLeftStipBits(bits, 16)); + else +#endif + mask = fbBits[FbLeftStipBits(bits, pixelsPerDst)]; + if (fbLane) { + fbTransparentSpan(dst, mask & startmask, fgxor, 1); + } + else + { + if (mask || !transparent) + FbDoLeftMaskByteStippleRRop(dst, mask, + fgand, fgxor, bgand, bgxor, + startbyte, startmask); + } + bits = FbStipLeft(bits, pixelsPerDst); + dst++; + n--; + w--; + } + /* + * Consume stipple bits across scanline + */ + for (;;) { + w -= n; + if (copy) { + while (n--) { +#if FB_UNIT > 32 + if (pixelsPerDst == 16) + mask = FbStipple16Bits(FbLeftStipBits(bits, 16)); + else +#endif + mask = fbBits[FbLeftStipBits(bits, pixelsPerDst)]; + *dst = FbOpaqueStipple(mask, fgxor, bgxor); + dst++; + bits = FbStipLeft(bits, pixelsPerDst); + } + } + else { + if (fbLane) { + while (bits && n) { + switch (fbLane[FbLeftStipBits(bits, pixelsPerDst)]) { + LaneCases((CARD8 *) dst); + } + bits = FbStipLeft(bits, pixelsPerDst); + dst++; + n--; + } + dst += n; + } + else + { + while (n--) { + left = FbLeftStipBits(bits, pixelsPerDst); + if (left || !transparent) { + mask = fbBits[left]; + *dst = FbStippleRRop(*dst, mask, + fgand, fgxor, bgand, + bgxor); + } + dst++; + bits = FbStipLeft(bits, pixelsPerDst); + } + } + } + if (!w) + break; + /* + * Load another set and reset number of available units + */ + LoadBits; + n = unitsPerSrc; + if (n > w) + n = w; + } + } + /* + * Consume stipple bits for endmask + */ + if (endmask) { + if (endNeedsLoad) { + LoadBits; + } +#if FB_UNIT > 32 + if (pixelsPerDst == 16) + mask = FbStipple16Bits(FbLeftStipBits(bits, 16)); + else +#endif + mask = fbBits[FbLeftStipBits(bits, pixelsPerDst)]; + if (fbLane) { + fbTransparentSpan(dst, mask & endmask, fgxor, 1); + } + else + { + if (mask || !transparent) + FbDoRightMaskByteStippleRRop(dst, mask, + fgand, fgxor, bgand, bgxor, + endbyte, endmask); + } + } + dst += dstStride; + src += srcStride; + } +} + + +/* + * Crufty macros to initialize the mask array, most of this + * is to avoid compile-time warnings about shift overflow + */ + +#if BITMAP_BIT_ORDER == MSBFirst +#define Mask24Pos(x,r) ((x)*24-(r)) +#else +#define Mask24Pos(x,r) ((x)*24-((r) ? 24 - (r) : 0)) +#endif + +#define Mask24Neg(x,r) (Mask24Pos(x,r) < 0 ? -Mask24Pos(x,r) : 0) +#define Mask24Check(x,r) (Mask24Pos(x,r) < 0 ? 0 : \ + Mask24Pos(x,r) >= FB_UNIT ? 0 : Mask24Pos(x,r)) + +#define Mask24(x,r) (Mask24Pos(x,r) < FB_UNIT ? \ + (Mask24Pos(x,r) < 0 ? \ + 0xffffff >> Mask24Neg (x,r) : \ + 0xffffff << Mask24Check(x,r)) : 0) + +#define SelMask24(b,n,r) ((((b) >> n) & 1) * Mask24(n,r)) + +/* + * Untested for MSBFirst or FB_UNIT == 32 + */ + +#if FB_UNIT == 64 +#define C4_24(b,r) \ + (SelMask24(b,0,r) | \ + SelMask24(b,1,r) | \ + SelMask24(b,2,r) | \ + SelMask24(b,3,r)) + +#define FbStip24New(rot) (2 + (rot != 0)) +#define FbStip24Len 4 + +const FbBits fbStipple24Bits[3][1 << FbStip24Len] = { + /* rotate 0 */ + { + C4_24(0, 0), C4_24(1, 0), C4_24(2, 0), C4_24(3, 0), + C4_24(4, 0), C4_24(5, 0), C4_24(6, 0), C4_24(7, 0), + C4_24(8, 0), C4_24(9, 0), C4_24(10, 0), C4_24(11, 0), + C4_24(12, 0), C4_24(13, 0), C4_24(14, 0), C4_24(15, 0), + }, + /* rotate 8 */ + { + C4_24(0, 8), C4_24(1, 8), C4_24(2, 8), C4_24(3, 8), + C4_24(4, 8), C4_24(5, 8), C4_24(6, 8), C4_24(7, 8), + C4_24(8, 8), C4_24(9, 8), C4_24(10, 8), C4_24(11, 8), + C4_24(12, 8), C4_24(13, 8), C4_24(14, 8), C4_24(15, 8), + }, + /* rotate 16 */ + { + C4_24(0, 16), C4_24(1, 16), C4_24(2, 16), C4_24(3, 16), + C4_24(4, 16), C4_24(5, 16), C4_24(6, 16), C4_24(7, 16), + C4_24(8, 16), C4_24(9, 16), C4_24(10, 16), C4_24(11, 16), + C4_24(12, 16), C4_24(13, 16), C4_24(14, 16), C4_24(15, 16), + } +}; + +#endif + +#if FB_UNIT == 32 +#define C2_24(b,r) \ + (SelMask24(b,0,r) | \ + SelMask24(b,1,r)) + +#define FbStip24Len 2 +#if BITMAP_BIT_ORDER == MSBFirst +#define FbStip24New(rot) (1 + (rot == 0)) +#else +#define FbStip24New(rot) (1 + (rot == 8)) +#endif + +const FbBits fbStipple24Bits[3][1 << FbStip24Len] = { + /* rotate 0 */ + { + C2_24(0, 0), C2_24(1, 0), C2_24(2, 0), C2_24(3, 0), + }, + /* rotate 8 */ + { + C2_24(0, 8), C2_24(1, 8), C2_24(2, 8), C2_24(3, 8), + }, + /* rotate 16 */ + { + C2_24(0, 16), C2_24(1, 16), C2_24(2, 16), C2_24(3, 16), + } +}; +#endif + +#if BITMAP_BIT_ORDER == LSBFirst + +#define FbMergeStip24Bits(left, right, new) \ + (FbStipLeft (left, new) | FbStipRight ((right), (FbStip24Len - (new)))) + +#define FbMergePartStip24Bits(left, right, llen, rlen) \ + (left | FbStipRight(right, llen)) + +#else + +#define FbMergeStip24Bits(left, right, new) \ + ((FbStipLeft (left, new) & ((1 << FbStip24Len) - 1)) | right) + +#define FbMergePartStip24Bits(left, right, llen, rlen) \ + (FbStipLeft(left, rlen) | right) + +#endif + +#define fbFirstStipBits(len,stip) {\ + int __len = (len); \ + if (len <= remain) { \ + stip = FbLeftStipBits(bits, len); \ + } else { \ + stip = FbLeftStipBits(bits, remain); \ + bits = (src < srcEnd ? *src++ : 0); \ + __len = (len) - remain; \ + stip = FbMergePartStip24Bits(stip, FbLeftStipBits(bits, __len), \ + remain, __len); \ + remain = FB_STIP_UNIT; \ + } \ + bits = FbStipLeft (bits, __len); \ + remain -= __len; \ +} + +#define fbInitStipBits(offset,len,stip) {\ + bits = FbStipLeft (*src++,offset); \ + remain = FB_STIP_UNIT - offset; \ + fbFirstStipBits(len,stip); \ + stip = FbMergeStip24Bits (0, stip, len); \ +} + +#define fbNextStipBits(rot,stip) {\ + int __new = FbStip24New(rot); \ + FbStip __right; \ + fbFirstStipBits(__new, __right); \ + stip = FbMergeStip24Bits (stip, __right, __new); \ + rot = FbNext24Rot (rot); \ +} + +/* + * Use deep mask tables that incorporate rotation, pull + * a variable number of bits out of the stipple and + * reuse the right bits as needed for the next write + * + * Yes, this is probably too much code, but most 24-bpp screens + * have no acceleration so this code is used for stipples, copyplane + * and text + */ +void +fbBltOne24(FbStip * srcLine, FbStride srcStride, /* FbStip units per scanline */ + int srcX, /* bit position of source */ + FbBits * dst, FbStride dstStride, /* FbBits units per scanline */ + int dstX, /* bit position of dest */ + int dstBpp, /* bits per destination unit */ + int width, /* width in bits of destination */ + int height, /* height in scanlines */ + FbBits fgand, /* rrop values */ + FbBits fgxor, FbBits bgand, FbBits bgxor) +{ + FbStip *src, *srcEnd; + + FbBits leftMask, rightMask, mask; + + int nlMiddle, nl; + + FbStip stip, bits; + + int remain; + + int dstS; + + int firstlen; + + int rot0, rot; + + int nDst; + + /* + * Do not read past the end of the buffer! + */ + srcEnd = srcLine + height * srcStride; + + srcLine += srcX >> FB_STIP_SHIFT; + dst += dstX >> FB_SHIFT; + srcX &= FB_STIP_MASK; + dstX &= FB_MASK; + rot0 = FbFirst24Rot(dstX); + + FbMaskBits(dstX, width, leftMask, nlMiddle, rightMask); + + dstS = (dstX + 23) / 24; + firstlen = FbStip24Len - dstS; + + nDst = nlMiddle; + if (leftMask) + nDst++; + dstStride -= nDst; + + /* opaque copy */ + if (bgand == 0 && fgand == 0) { + while (height--) { + rot = rot0; + src = srcLine; + srcLine += srcStride; + fbInitStipBits(srcX, firstlen, stip); + if (leftMask) { + mask = fbStipple24Bits[rot >> 3][stip]; + *dst = (*dst & ~leftMask) | (FbOpaqueStipple(mask, + FbRot24(fgxor, + rot), + FbRot24(bgxor, + rot)) + & leftMask); + dst++; + fbNextStipBits(rot, stip); + } + nl = nlMiddle; + while (nl--) { + mask = fbStipple24Bits[rot >> 3][stip]; + *dst = FbOpaqueStipple(mask, + FbRot24(fgxor, rot), + FbRot24(bgxor, rot)); + dst++; + fbNextStipBits(rot, stip); + } + if (rightMask) { + mask = fbStipple24Bits[rot >> 3][stip]; + *dst = (*dst & ~rightMask) | (FbOpaqueStipple(mask, + FbRot24(fgxor, + rot), + FbRot24(bgxor, + rot)) + & rightMask); + } + dst += dstStride; + src += srcStride; + } + } + /* transparent copy */ + else if (bgand == FB_ALLONES && bgxor == 0 && fgand == 0) { + while (height--) { + rot = rot0; + src = srcLine; + srcLine += srcStride; + fbInitStipBits(srcX, firstlen, stip); + if (leftMask) { + if (stip) { + mask = fbStipple24Bits[rot >> 3][stip] & leftMask; + *dst = (*dst & ~mask) | (FbRot24(fgxor, rot) & mask); + } + dst++; + fbNextStipBits(rot, stip); + } + nl = nlMiddle; + while (nl--) { + if (stip) { + mask = fbStipple24Bits[rot >> 3][stip]; + *dst = (*dst & ~mask) | (FbRot24(fgxor, rot) & mask); + } + dst++; + fbNextStipBits(rot, stip); + } + if (rightMask) { + if (stip) { + mask = fbStipple24Bits[rot >> 3][stip] & rightMask; + *dst = (*dst & ~mask) | (FbRot24(fgxor, rot) & mask); + } + } + dst += dstStride; + } + } + else { + while (height--) { + rot = rot0; + src = srcLine; + srcLine += srcStride; + fbInitStipBits(srcX, firstlen, stip); + if (leftMask) { + mask = fbStipple24Bits[rot >> 3][stip]; + *dst = FbStippleRRopMask(*dst, mask, + FbRot24(fgand, rot), + FbRot24(fgxor, rot), + FbRot24(bgand, rot), + FbRot24(bgxor, rot), leftMask); + dst++; + fbNextStipBits(rot, stip); + } + nl = nlMiddle; + while (nl--) { + mask = fbStipple24Bits[rot >> 3][stip]; + *dst = FbStippleRRop(*dst, mask, + FbRot24(fgand, rot), + FbRot24(fgxor, rot), + FbRot24(bgand, rot), FbRot24(bgxor, rot)); + dst++; + fbNextStipBits(rot, stip); + } + if (rightMask) { + mask = fbStipple24Bits[rot >> 3][stip]; + *dst = FbStippleRRopMask(*dst, mask, + FbRot24(fgand, rot), + FbRot24(fgxor, rot), + FbRot24(bgand, rot), + FbRot24(bgxor, rot), rightMask); + } + dst += dstStride; + } + } +} + +/* + * Not very efficient, but simple -- copy a single plane + * from an N bit image to a 1 bit image + */ + +void +fbBltPlane(FbBits * src, + FbStride srcStride, + int srcX, + int srcBpp, + FbStip * dst, + FbStride dstStride, + int dstX, + int width, + int height, + FbStip fgand, + FbStip fgxor, FbStip bgand, FbStip bgxor, Pixel planeMask) +{ + FbBits *s; + + FbBits pm; + + FbBits srcMask; + + FbBits srcMaskFirst; + + FbBits srcMask0 = 0; + + FbBits srcBits; + + FbStip dstBits; + + FbStip *d; + + FbStip dstMask; + + FbStip dstMaskFirst; + + FbStip dstUnion; + + int w; + + int wt; + + int rot0; + + if (!width) + return; + + src += srcX >> FB_SHIFT; + srcX &= FB_MASK; + + dst += dstX >> FB_STIP_SHIFT; + dstX &= FB_STIP_MASK; + + w = width / srcBpp; + + pm = fbReplicatePixel(planeMask, srcBpp); + if (srcBpp == 24) { + int tmpw = 24; + + rot0 = FbFirst24Rot(srcX); + if (srcX + tmpw > FB_UNIT) + tmpw = FB_UNIT - srcX; + srcMaskFirst = FbRot24(pm, rot0) & FbBitsMask(srcX, tmpw); + } + else + { + rot0 = 0; + srcMaskFirst = pm & FbBitsMask(srcX, srcBpp); + srcMask0 = pm & FbBitsMask(0, srcBpp); + } + + dstMaskFirst = FbStipMask(dstX, 1); + while (height--) { + d = dst; + dst += dstStride; + s = src; + src += srcStride; + + srcMask = srcMaskFirst; + if (srcBpp == 24) + srcMask0 = FbRot24(pm, rot0) & FbBitsMask(0, srcBpp); + srcBits = *s++; + + dstMask = dstMaskFirst; + dstUnion = 0; + dstBits = 0; + + wt = w; + + while (wt--) { + if (!srcMask) { + srcBits = *s++; + if (srcBpp == 24) + srcMask0 = FbNext24Pix(srcMask0) & FbBitsMask(0, 24); + srcMask = srcMask0; + } + if (!dstMask) { + *d = FbStippleRRopMask(*d, dstBits, + fgand, fgxor, bgand, bgxor, dstUnion); + d++; + dstMask = FbStipMask(0, 1); + dstUnion = 0; + dstBits = 0; + } + if (srcBits & srcMask) + dstBits |= dstMask; + dstUnion |= dstMask; + if (srcBpp == FB_UNIT) + srcMask = 0; + else + srcMask = FbScrRight(srcMask, srcBpp); + dstMask = FbStipRight(dstMask, 1); + } + if (dstUnion) + *d = FbStippleRRopMask(*d, dstBits, + fgand, fgxor, bgand, bgxor, dstUnion); + } +} diff --git a/fb/fbcmap.c b/fb/fbcmap.c new file mode 100644 index 0000000..3043e9a --- /dev/null +++ b/fb/fbcmap.c @@ -0,0 +1,114 @@ +/************************************************************ +Copyright 1987 by Sun Microsystems, Inc. Mountain View, CA. + + 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 no- +tice appear in all copies and that both that copyright no- +tice and this permission notice appear in supporting docu- +mentation, and that the names of Sun or X Consortium +not be used in advertising or publicity pertaining to +distribution of the software without specific prior +written permission. Sun and X Consortium make no +representations about the suitability of this software for +any purpose. It is provided "as is" without any express or +implied warranty. + +SUN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT- +NESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SUN BE LI- +ABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH +THE USE OR PERFORMANCE OF THIS SOFTWARE. + +********************************************************/ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#include +#include "scrnintstr.h" +#include "colormapst.h" +#include "resource.h" +#include "fb.h" +#include "micmap.h" + +int +fbListInstalledColormaps(ScreenPtr pScreen, Colormap * pmaps) +{ + return miListInstalledColormaps(pScreen, pmaps); +} + +void +fbInstallColormap(ColormapPtr pmap) +{ + miInstallColormap(pmap); +} + +void +fbUninstallColormap(ColormapPtr pmap) +{ + miUninstallColormap(pmap); +} + +void +fbResolveColor(unsigned short *pred, + unsigned short *pgreen, unsigned short *pblue, VisualPtr pVisual) +{ + miResolveColor(pred, pgreen, pblue, pVisual); +} + +Bool +fbInitializeColormap(ColormapPtr pmap) +{ + return miInitializeColormap(pmap); +} + +int +fbExpandDirectColors(ColormapPtr pmap, + int ndef, xColorItem * indefs, xColorItem * outdefs) +{ + return miExpandDirectColors(pmap, ndef, indefs, outdefs); +} + +Bool +fbCreateDefColormap(ScreenPtr pScreen) +{ + return miCreateDefColormap(pScreen); +} + +void +fbClearVisualTypes(void) +{ + miClearVisualTypes(); +} + +Bool +fbSetVisualTypes(int depth, int visuals, int bitsPerRGB) +{ + return miSetVisualTypes(depth, visuals, bitsPerRGB, -1); +} + +/* + * Given a list of formats for a screen, create a list + * of visuals and depths for the screen which coorespond to + * the set which can be used with this version of fb. + */ + +Bool +fbInitVisuals(VisualPtr * visualp, + DepthPtr * depthp, + int *nvisualp, + int *ndepthp, + int *rootDepthp, + VisualID * defaultVisp, unsigned long sizes, int bitsPerRGB) +{ + return miInitVisuals(visualp, depthp, nvisualp, ndepthp, rootDepthp, + defaultVisp, sizes, bitsPerRGB, -1); +} diff --git a/fb/fbcompose.c b/fb/fbcompose.c new file mode 100644 index 0000000..b8c1ebb --- /dev/null +++ b/fb/fbcompose.c @@ -0,0 +1,4284 @@ +/* + * + * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc. + * 2005 Lars Knoll & Zack Rusin, Trolltech + * + * 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, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "fb.h" + + +#include +#include +#include +#include + +#include "picturestr.h" +#include "mipict.h" +#include "fbpict.h" + +#define mod(a,b) ((b) == 1 ? 0 : (a) >= 0 ? (a) % (b) : (b) - (-a) % (b)) + +#define SCANLINE_BUFFER_LENGTH 2048 + +typedef FASTCALL void (*fetchProc) (const FbBits * bits, int x, int width, + CARD32 *buffer, miIndexedPtr indexed); + +/* + * All of the fetch functions + */ + +static FASTCALL void +fbFetch_a8r8g8b8(const FbBits * bits, int x, int width, CARD32 *buffer, + miIndexedPtr indexed) +{ + memcpy(buffer, (const CARD32 *) bits + x, width * sizeof(CARD32)); +} + +static FASTCALL void +fbFetch_x8r8g8b8(const FbBits * bits, int x, int width, CARD32 *buffer, + miIndexedPtr indexed) +{ + const CARD32 *pixel = (const CARD32 *) bits + x; + + const CARD32 *end = pixel + width; + + while (pixel < end) { + *buffer++ = *pixel++ | 0xff000000; + } +} + +static FASTCALL void +fbFetch_a8b8g8r8(const FbBits * bits, int x, int width, CARD32 *buffer, + miIndexedPtr indexed) +{ + const CARD32 *pixel = (CARD32 *) bits + x; + + const CARD32 *end = pixel + width; + + while (pixel < end) { + *buffer++ = ((*pixel & 0xff00ff00) | + ((*pixel >> 16) & 0xff) | ((*pixel & 0xff) << 16)); + ++pixel; + } +} + +static FASTCALL void +fbFetch_x8b8g8r8(const FbBits * bits, int x, int width, CARD32 *buffer, + miIndexedPtr indexed) +{ + const CARD32 *pixel = (CARD32 *) bits + x; + + const CARD32 *end = pixel + width; + + while (pixel < end) { + *buffer++ = 0xff000000 | + ((*pixel & 0x0000ff00) | + ((*pixel >> 16) & 0xff) | ((*pixel & 0xff) << 16)); + ++pixel; + } +} + +static FASTCALL void +fbFetch_r8g8b8(const FbBits * bits, int x, int width, CARD32 *buffer, + miIndexedPtr indexed) +{ + const CARD8 *pixel = (const CARD8 *) bits + 3 * x; + + const CARD8 *end = pixel + 3 * width; + + while (pixel < end) { + CARD32 b = Fetch24(pixel) | 0xff000000; + + pixel += 3; + *buffer++ = b; + } +} + +static FASTCALL void +fbFetch_b8g8r8(const FbBits * bits, int x, int width, CARD32 *buffer, + miIndexedPtr indexed) +{ + const CARD8 *pixel = (const CARD8 *) bits + 3 * x; + + const CARD8 *end = pixel + 3 * width; + + while (pixel < end) { + CARD32 b = 0xff000000; + +#if IMAGE_BYTE_ORDER == MSBFirst + b |= (*pixel++); + b |= (*pixel++ << 8); + b |= (*pixel++ << 16); +#else + b |= (*pixel++ << 16); + b |= (*pixel++ << 8); + b |= (*pixel++); +#endif + *buffer++ = b; + } +} + +static FASTCALL void +fbFetch_r5g6b5(const FbBits * bits, int x, int width, CARD32 *buffer, + miIndexedPtr indexed) +{ + const CARD16 *pixel = (const CARD16 *) bits + x; + + const CARD16 *end = pixel + width; + + while (pixel < end) { + CARD32 p = *pixel++; + + CARD32 r = (((p) << 3) & 0xf8) | + (((p) << 5) & 0xfc00) | (((p) << 8) & 0xf80000); + r |= (r >> 5) & 0x70007; + r |= (r >> 6) & 0x300; + *buffer++ = 0xff000000 | r; + } +} + +static FASTCALL void +fbFetch_b5g6r5(const FbBits * bits, int x, int width, CARD32 *buffer, + miIndexedPtr indexed) +{ + const CARD16 *pixel = (const CARD16 *) bits + x; + + const CARD16 *end = pixel + width; + + while (pixel < end) { + CARD32 p = *pixel++; + + CARD32 r, g, b; + + b = ((p & 0xf800) | ((p & 0xe000) >> 5)) >> 8; + g = ((p & 0x07e0) | ((p & 0x0600) >> 6)) << 5; + r = ((p & 0x001c) | ((p & 0x001f) << 5)) << 14; + *buffer++ = (0xff000000 | r | g | b); + } +} + +static FASTCALL void +fbFetch_a1r5g5b5(const FbBits * bits, int x, int width, CARD32 *buffer, + miIndexedPtr indexed) +{ + const CARD16 *pixel = (const CARD16 *) bits + x; + + const CARD16 *end = pixel + width; + + while (pixel < end) { + CARD32 p = *pixel++; + + CARD32 r, g, b, a; + + a = (CARD32) ((CARD8) (0 - ((p & 0x8000) >> 15))) << 24; + r = ((p & 0x7c00) | ((p & 0x7000) >> 5)) << 9; + g = ((p & 0x03e0) | ((p & 0x0380) >> 5)) << 6; + b = ((p & 0x001c) | ((p & 0x001f) << 5)) >> 2; + *buffer++ = (a | r | g | b); + } +} + +static FASTCALL void +fbFetch_x1r5g5b5(const FbBits * bits, int x, int width, CARD32 *buffer, + miIndexedPtr indexed) +{ + const CARD16 *pixel = (const CARD16 *) bits + x; + + const CARD16 *end = pixel + width; + + while (pixel < end) { + CARD32 p = *pixel++; + + CARD32 r, g, b; + + r = ((p & 0x7c00) | ((p & 0x7000) >> 5)) << 9; + g = ((p & 0x03e0) | ((p & 0x0380) >> 5)) << 6; + b = ((p & 0x001c) | ((p & 0x001f) << 5)) >> 2; + *buffer++ = (0xff000000 | r | g | b); + } +} + +static FASTCALL void +fbFetch_a1b5g5r5(const FbBits * bits, int x, int width, CARD32 *buffer, + miIndexedPtr indexed) +{ + const CARD16 *pixel = (const CARD16 *) bits + x; + + const CARD16 *end = pixel + width; + + while (pixel < end) { + CARD32 p = *pixel++; + + CARD32 r, g, b, a; + + a = (CARD32) ((CARD8) (0 - ((p & 0x8000) >> 15))) << 24; + b = ((p & 0x7c00) | ((p & 0x7000) >> 5)) >> 7; + g = ((p & 0x03e0) | ((p & 0x0380) >> 5)) << 6; + r = ((p & 0x001c) | ((p & 0x001f) << 5)) << 14; + *buffer++ = (a | r | g | b); + } +} + +static FASTCALL void +fbFetch_x1b5g5r5(const FbBits * bits, int x, int width, CARD32 *buffer, + miIndexedPtr indexed) +{ + const CARD16 *pixel = (const CARD16 *) bits + x; + + const CARD16 *end = pixel + width; + + while (pixel < end) { + CARD32 p = *pixel++; + + CARD32 r, g, b; + + b = ((p & 0x7c00) | ((p & 0x7000) >> 5)) >> 7; + g = ((p & 0x03e0) | ((p & 0x0380) >> 5)) << 6; + r = ((p & 0x001c) | ((p & 0x001f) << 5)) << 14; + *buffer++ = (0xff000000 | r | g | b); + } +} + +static FASTCALL void +fbFetch_a4r4g4b4(const FbBits * bits, int x, int width, CARD32 *buffer, + miIndexedPtr indexed) +{ + const CARD16 *pixel = (const CARD16 *) bits + x; + + const CARD16 *end = pixel + width; + + while (pixel < end) { + CARD32 p = *pixel++; + + CARD32 r, g, b, a; + + a = ((p & 0xf000) | ((p & 0xf000) >> 4)) << 16; + r = ((p & 0x0f00) | ((p & 0x0f00) >> 4)) << 12; + g = ((p & 0x00f0) | ((p & 0x00f0) >> 4)) << 8; + b = ((p & 0x000f) | ((p & 0x000f) << 4)); + *buffer++ = (a | r | g | b); + } +} + +static FASTCALL void +fbFetch_x4r4g4b4(const FbBits * bits, int x, int width, CARD32 *buffer, + miIndexedPtr indexed) +{ + const CARD16 *pixel = (const CARD16 *) bits + x; + + const CARD16 *end = pixel + width; + + while (pixel < end) { + CARD32 p = *pixel++; + + CARD32 r, g, b; + + r = ((p & 0x0f00) | ((p & 0x0f00) >> 4)) << 12; + g = ((p & 0x00f0) | ((p & 0x00f0) >> 4)) << 8; + b = ((p & 0x000f) | ((p & 0x000f) << 4)); + *buffer++ = (0xff000000 | r | g | b); + } +} + +static FASTCALL void +fbFetch_a4b4g4r4(const FbBits * bits, int x, int width, CARD32 *buffer, + miIndexedPtr indexed) +{ + const CARD16 *pixel = (const CARD16 *) bits + x; + + const CARD16 *end = pixel + width; + + while (pixel < end) { + CARD32 p = *pixel++; + + CARD32 r, g, b, a; + + a = ((p & 0xf000) | ((p & 0xf000) >> 4)) << 16; + b = ((p & 0x0f00) | ((p & 0x0f00) >> 4)) >> 4; + g = ((p & 0x00f0) | ((p & 0x00f0) >> 4)) << 8; + r = ((p & 0x000f) | ((p & 0x000f) << 4)) << 16; + *buffer++ = (a | r | g | b); + } +} + +static FASTCALL void +fbFetch_x4b4g4r4(const FbBits * bits, int x, int width, CARD32 *buffer, + miIndexedPtr indexed) +{ + const CARD16 *pixel = (const CARD16 *) bits + x; + + const CARD16 *end = pixel + width; + + while (pixel < end) { + CARD32 p = *pixel++; + + CARD32 r, g, b; + + b = ((p & 0x0f00) | ((p & 0x0f00) >> 4)) >> 4; + g = ((p & 0x00f0) | ((p & 0x00f0) >> 4)) << 8; + r = ((p & 0x000f) | ((p & 0x000f) << 4)) << 16; + *buffer++ = (0xff000000 | r | g | b); + } +} + +static FASTCALL void +fbFetch_a8(const FbBits * bits, int x, int width, CARD32 *buffer, + miIndexedPtr indexed) +{ + const CARD8 *pixel = (const CARD8 *) bits + x; + + const CARD8 *end = pixel + width; + + while (pixel < end) { + *buffer++ = (*pixel++) << 24; + } +} + +static FASTCALL void +fbFetch_r3g3b2(const FbBits * bits, int x, int width, CARD32 *buffer, + miIndexedPtr indexed) +{ + const CARD8 *pixel = (const CARD8 *) bits + x; + + const CARD8 *end = pixel + width; + + while (pixel < end) { + CARD32 p = *pixel++; + + CARD32 r, g, b; + + r = ((p & 0xe0) | ((p & 0xe0) >> 3) | ((p & 0xc0) >> 6)) << 16; + g = ((p & 0x1c) | ((p & 0x18) >> 3) | ((p & 0x1c) << 3)) << 8; + b = (((p & 0x03)) | + ((p & 0x03) << 2) | ((p & 0x03) << 4) | ((p & 0x03) << 6)); + *buffer++ = (0xff000000 | r | g | b); + } +} + +static FASTCALL void +fbFetch_b2g3r3(const FbBits * bits, int x, int width, CARD32 *buffer, + miIndexedPtr indexed) +{ + const CARD8 *pixel = (const CARD8 *) bits + x; + + const CARD8 *end = pixel + width; + + while (pixel < end) { + CARD32 p = *pixel++; + + CARD32 r, g, b; + + b = (((p & 0xc0)) | + ((p & 0xc0) >> 2) | ((p & 0xc0) >> 4) | ((p & 0xc0) >> 6)); + g = ((p & 0x38) | ((p & 0x38) >> 3) | ((p & 0x30) << 2)) << 8; + r = (((p & 0x07)) | ((p & 0x07) << 3) | ((p & 0x06) << 6)) << 16; + *buffer++ = (0xff000000 | r | g | b); + } +} + +static FASTCALL void +fbFetch_a2r2g2b2(const FbBits * bits, int x, int width, CARD32 *buffer, + miIndexedPtr indexed) +{ + const CARD8 *pixel = (const CARD8 *) bits + x; + + const CARD8 *end = pixel + width; + + while (pixel < end) { + CARD32 p = *pixel++; + + CARD32 a, r, g, b; + + a = ((p & 0xc0) * 0x55) << 18; + r = ((p & 0x30) * 0x55) << 12; + g = ((p & 0x0c) * 0x55) << 6; + b = ((p & 0x03) * 0x55); + *buffer++ = a | r | g | b; + } +} + +static FASTCALL void +fbFetch_a2b2g2r2(const FbBits * bits, int x, int width, CARD32 *buffer, + miIndexedPtr indexed) +{ + const CARD8 *pixel = (const CARD8 *) bits + x; + + const CARD8 *end = pixel + width; + + while (pixel < end) { + CARD32 p = *pixel++; + + CARD32 a, r, g, b; + + a = ((p & 0xc0) * 0x55) << 18; + b = ((p & 0x30) * 0x55) >> 6; + g = ((p & 0x0c) * 0x55) << 6; + r = ((p & 0x03) * 0x55) << 16; + *buffer++ = a | r | g | b; + } +} + +static FASTCALL void +fbFetch_c8(const FbBits * bits, int x, int width, CARD32 *buffer, + miIndexedPtr indexed) +{ + const CARD8 *pixel = (const CARD8 *) bits + x; + + const CARD8 *end = pixel + width; + + while (pixel < end) { + CARD32 p = *pixel++; + + *buffer++ = indexed->rgba[p]; + } +} + +static FASTCALL void +fbFetch_x4a4(const FbBits * bits, int x, int width, CARD32 *buffer, + miIndexedPtr indexed) +{ + const CARD8 *pixel = (const CARD8 *) bits + x; + + const CARD8 *end = pixel + width; + + while (pixel < end) { + CARD8 p = (*pixel++) & 0xf; + + *buffer++ = (p | (p << 4)) << 24; + } +} + +#define Fetch8(l,o) (((CARD8 *) (l))[(o) >> 2]) +#if IMAGE_BYTE_ORDER == MSBFirst +#define Fetch4(l,o) ((o) & 2 ? Fetch8(l,o) & 0xf : Fetch8(l,o) >> 4) +#else +#define Fetch4(l,o) ((o) & 2 ? Fetch8(l,o) >> 4 : Fetch8(l,o) & 0xf) +#endif + +static FASTCALL void +fbFetch_a4(const FbBits * bits, int x, int width, CARD32 *buffer, + miIndexedPtr indexed) +{ + int i; + + for (i = 0; i < width; ++i) { + CARD32 p = Fetch4(bits, i + x); + + p |= p << 4; + *buffer++ = p << 24; + } +} + +static FASTCALL void +fbFetch_r1g2b1(const FbBits * bits, int x, int width, CARD32 *buffer, + miIndexedPtr indexed) +{ + int i; + + for (i = 0; i < width; ++i) { + CARD32 p = Fetch4(bits, i + x); + + CARD32 r, g, b; + + r = ((p & 0x8) * 0xff) << 13; + g = ((p & 0x6) * 0x55) << 7; + b = ((p & 0x1) * 0xff); + *buffer++ = 0xff000000 | r | g | b; + } +} + +static FASTCALL void +fbFetch_b1g2r1(const FbBits * bits, int x, int width, CARD32 *buffer, + miIndexedPtr indexed) +{ + int i; + + for (i = 0; i < width; ++i) { + CARD32 p = Fetch4(bits, i + x); + + CARD32 r, g, b; + + b = ((p & 0x8) * 0xff) >> 3; + g = ((p & 0x6) * 0x55) << 7; + r = ((p & 0x1) * 0xff) << 16; + *buffer++ = 0xff000000 | r | g | b; + } +} + +static FASTCALL void +fbFetch_a1r1g1b1(const FbBits * bits, int x, int width, CARD32 *buffer, + miIndexedPtr indexed) +{ + int i; + + for (i = 0; i < width; ++i) { + CARD32 p = Fetch4(bits, i + x); + + CARD32 a, r, g, b; + + a = ((p & 0x8) * 0xff) << 21; + r = ((p & 0x4) * 0xff) << 14; + g = ((p & 0x2) * 0xff) << 7; + b = ((p & 0x1) * 0xff); + *buffer++ = a | r | g | b; + } +} + +static FASTCALL void +fbFetch_a1b1g1r1(const FbBits * bits, int x, int width, CARD32 *buffer, + miIndexedPtr indexed) +{ + int i; + + for (i = 0; i < width; ++i) { + CARD32 p = Fetch4(bits, i + x); + + CARD32 a, r, g, b; + + a = ((p & 0x8) * 0xff) << 21; + r = ((p & 0x4) * 0xff) >> 3; + g = ((p & 0x2) * 0xff) << 7; + b = ((p & 0x1) * 0xff) << 16; + *buffer++ = a | r | g | b; + } +} + +static FASTCALL void +fbFetch_c4(const FbBits * bits, int x, int width, CARD32 *buffer, + miIndexedPtr indexed) +{ + int i; + + for (i = 0; i < width; ++i) { + CARD32 p = Fetch4(bits, i + x); + + *buffer++ = indexed->rgba[p]; + } +} + +static FASTCALL void +fbFetch_a1(const FbBits * bits, int x, int width, CARD32 *buffer, + miIndexedPtr indexed) +{ + int i; + + for (i = 0; i < width; ++i) { + CARD32 p = ((CARD32 *) bits)[(i + x) >> 5]; + + CARD32 a; + +#if BITMAP_BIT_ORDER == MSBFirst + a = p >> (0x1f - ((i + x) & 0x1f)); +#else + a = p >> ((i + x) & 0x1f); +#endif + a = a & 1; + a |= a << 1; + a |= a << 2; + a |= a << 4; + *buffer++ = a << 24; + } +} + +static FASTCALL void +fbFetch_g1(const FbBits * bits, int x, int width, CARD32 *buffer, + miIndexedPtr indexed) +{ + int i; + + for (i = 0; i < width; ++i) { + CARD32 p = ((CARD32 *) bits)[(i + x) >> 5]; + + CARD32 a; + +#if BITMAP_BIT_ORDER == MSBFirst + a = p >> (0x1f - ((i + x) & 0x1f)); +#else + a = p >> ((i + x) & 0x1f); +#endif + a = a & 1; + *buffer++ = indexed->rgba[a]; + } +} + +static fetchProc +fetchProcForPicture(PicturePtr pict) +{ + switch (pict->format) { + case PICT_a8r8g8b8: + return fbFetch_a8r8g8b8; + case PICT_x8r8g8b8: + return fbFetch_x8r8g8b8; + case PICT_a8b8g8r8: + return fbFetch_a8b8g8r8; + case PICT_x8b8g8r8: + return fbFetch_x8b8g8r8; + + /* 24bpp formats */ + case PICT_r8g8b8: + return fbFetch_r8g8b8; + case PICT_b8g8r8: + return fbFetch_b8g8r8; + + /* 16bpp formats */ + case PICT_r5g6b5: + return fbFetch_r5g6b5; + case PICT_b5g6r5: + return fbFetch_b5g6r5; + + case PICT_a1r5g5b5: + return fbFetch_a1r5g5b5; + case PICT_x1r5g5b5: + return fbFetch_x1r5g5b5; + case PICT_a1b5g5r5: + return fbFetch_a1b5g5r5; + case PICT_x1b5g5r5: + return fbFetch_x1b5g5r5; + case PICT_a4r4g4b4: + return fbFetch_a4r4g4b4; + case PICT_x4r4g4b4: + return fbFetch_x4r4g4b4; + case PICT_a4b4g4r4: + return fbFetch_a4b4g4r4; + case PICT_x4b4g4r4: + return fbFetch_x4b4g4r4; + + /* 8bpp formats */ + case PICT_a8: + return fbFetch_a8; + case PICT_r3g3b2: + return fbFetch_r3g3b2; + case PICT_b2g3r3: + return fbFetch_b2g3r3; + case PICT_a2r2g2b2: + return fbFetch_a2r2g2b2; + case PICT_a2b2g2r2: + return fbFetch_a2b2g2r2; + case PICT_c8: + return fbFetch_c8; + case PICT_g8: + return fbFetch_c8; + case PICT_x4a4: + return fbFetch_x4a4; + + /* 4bpp formats */ + case PICT_a4: + return fbFetch_a4; + case PICT_r1g2b1: + return fbFetch_r1g2b1; + case PICT_b1g2r1: + return fbFetch_b1g2r1; + case PICT_a1r1g1b1: + return fbFetch_a1r1g1b1; + case PICT_a1b1g1r1: + return fbFetch_a1b1g1r1; + case PICT_c4: + return fbFetch_c4; + case PICT_g4: + return fbFetch_c4; + + /* 1bpp formats */ + case PICT_a1: + return fbFetch_a1; + case PICT_g1: + return fbFetch_g1; + } + + return NULL; +} + +/* + * Pixel wise fetching + */ + +typedef FASTCALL CARD32 (*fetchPixelProc) (const FbBits * bits, int offset, + miIndexedPtr indexed); + +static FASTCALL CARD32 +fbFetchPixel_a8r8g8b8(const FbBits * bits, int offset, miIndexedPtr indexed) +{ + return ((CARD32 *) bits)[offset]; +} + +static FASTCALL CARD32 +fbFetchPixel_x8r8g8b8(const FbBits * bits, int offset, miIndexedPtr indexed) +{ + return ((CARD32 *) bits)[offset] | 0xff000000; +} + +static FASTCALL CARD32 +fbFetchPixel_a8b8g8r8(const FbBits * bits, int offset, miIndexedPtr indexed) +{ + CARD32 pixel = ((CARD32 *) bits)[offset]; + + return ((pixel & 0xff000000) | + ((pixel >> 16) & 0xff) | + (pixel & 0x0000ff00) | ((pixel & 0xff) << 16)); +} + +static FASTCALL CARD32 +fbFetchPixel_x8b8g8r8(const FbBits * bits, int offset, miIndexedPtr indexed) +{ + CARD32 pixel = ((CARD32 *) bits)[offset]; + + return ((0xff000000) | + ((pixel >> 16) & 0xff) | + (pixel & 0x0000ff00) | ((pixel & 0xff) << 16)); +} + +static FASTCALL CARD32 +fbFetchPixel_r8g8b8(const FbBits * bits, int offset, miIndexedPtr indexed) +{ + CARD8 *pixel = ((CARD8 *) bits) + (offset * 3); + +#if IMAGE_BYTE_ORDER == MSBFirst + return (0xff000000 | (pixel[0] << 16) | (pixel[1] << 8) | (pixel[2])); +#else + return (0xff000000 | (pixel[2] << 16) | (pixel[1] << 8) | (pixel[0])); +#endif +} + +static FASTCALL CARD32 +fbFetchPixel_b8g8r8(const FbBits * bits, int offset, miIndexedPtr indexed) +{ + CARD8 *pixel = ((CARD8 *) bits) + (offset * 3); + +#if IMAGE_BYTE_ORDER == MSBFirst + return (0xff000000 | (pixel[2] << 16) | (pixel[1] << 8) | (pixel[0])); +#else + return (0xff000000 | (pixel[0] << 16) | (pixel[1] << 8) | (pixel[2])); +#endif +} + +static FASTCALL CARD32 +fbFetchPixel_r5g6b5(const FbBits * bits, int offset, miIndexedPtr indexed) +{ + CARD32 pixel = ((CARD16 *) bits)[offset]; + + CARD32 r, g, b; + + r = ((pixel & 0xf800) | ((pixel & 0xe000) >> 5)) << 8; + g = ((pixel & 0x07e0) | ((pixel & 0x0600) >> 6)) << 5; + b = ((pixel & 0x001c) | ((pixel & 0x001f) << 5)) >> 2; + return (0xff000000 | r | g | b); +} + +static FASTCALL CARD32 +fbFetchPixel_b5g6r5(const FbBits * bits, int offset, miIndexedPtr indexed) +{ + CARD32 pixel = ((CARD16 *) bits)[offset]; + + CARD32 r, g, b; + + b = ((pixel & 0xf800) | ((pixel & 0xe000) >> 5)) >> 8; + g = ((pixel & 0x07e0) | ((pixel & 0x0600) >> 6)) << 5; + r = ((pixel & 0x001c) | ((pixel & 0x001f) << 5)) << 14; + return (0xff000000 | r | g | b); +} + +static FASTCALL CARD32 +fbFetchPixel_a1r5g5b5(const FbBits * bits, int offset, miIndexedPtr indexed) +{ + CARD32 pixel = ((CARD16 *) bits)[offset]; + + CARD32 a, r, g, b; + + a = (CARD32) ((CARD8) (0 - ((pixel & 0x8000) >> 15))) << 24; + r = ((pixel & 0x7c00) | ((pixel & 0x7000) >> 5)) << 9; + g = ((pixel & 0x03e0) | ((pixel & 0x0380) >> 5)) << 6; + b = ((pixel & 0x001c) | ((pixel & 0x001f) << 5)) >> 2; + return (a | r | g | b); +} + +static FASTCALL CARD32 +fbFetchPixel_x1r5g5b5(const FbBits * bits, int offset, miIndexedPtr indexed) +{ + CARD32 pixel = ((CARD16 *) bits)[offset]; + + CARD32 r, g, b; + + r = ((pixel & 0x7c00) | ((pixel & 0x7000) >> 5)) << 9; + g = ((pixel & 0x03e0) | ((pixel & 0x0380) >> 5)) << 6; + b = ((pixel & 0x001c) | ((pixel & 0x001f) << 5)) >> 2; + return (0xff000000 | r | g | b); +} + +static FASTCALL CARD32 +fbFetchPixel_a1b5g5r5(const FbBits * bits, int offset, miIndexedPtr indexed) +{ + CARD32 pixel = ((CARD16 *) bits)[offset]; + + CARD32 a, r, g, b; + + a = (CARD32) ((CARD8) (0 - ((pixel & 0x8000) >> 15))) << 24; + b = ((pixel & 0x7c00) | ((pixel & 0x7000) >> 5)) >> 7; + g = ((pixel & 0x03e0) | ((pixel & 0x0380) >> 5)) << 6; + r = ((pixel & 0x001c) | ((pixel & 0x001f) << 5)) << 14; + return (a | r | g | b); +} + +static FASTCALL CARD32 +fbFetchPixel_x1b5g5r5(const FbBits * bits, int offset, miIndexedPtr indexed) +{ + CARD32 pixel = ((CARD16 *) bits)[offset]; + + CARD32 r, g, b; + + b = ((pixel & 0x7c00) | ((pixel & 0x7000) >> 5)) >> 7; + g = ((pixel & 0x03e0) | ((pixel & 0x0380) >> 5)) << 6; + r = ((pixel & 0x001c) | ((pixel & 0x001f) << 5)) << 14; + return (0xff000000 | r | g | b); +} + +static FASTCALL CARD32 +fbFetchPixel_a4r4g4b4(const FbBits * bits, int offset, miIndexedPtr indexed) +{ + CARD32 pixel = ((CARD16 *) bits)[offset]; + + CARD32 a, r, g, b; + + a = ((pixel & 0xf000) | ((pixel & 0xf000) >> 4)) << 16; + r = ((pixel & 0x0f00) | ((pixel & 0x0f00) >> 4)) << 12; + g = ((pixel & 0x00f0) | ((pixel & 0x00f0) >> 4)) << 8; + b = ((pixel & 0x000f) | ((pixel & 0x000f) << 4)); + return (a | r | g | b); +} + +static FASTCALL CARD32 +fbFetchPixel_x4r4g4b4(const FbBits * bits, int offset, miIndexedPtr indexed) +{ + CARD32 pixel = ((CARD16 *) bits)[offset]; + + CARD32 r, g, b; + + r = ((pixel & 0x0f00) | ((pixel & 0x0f00) >> 4)) << 12; + g = ((pixel & 0x00f0) | ((pixel & 0x00f0) >> 4)) << 8; + b = ((pixel & 0x000f) | ((pixel & 0x000f) << 4)); + return (0xff000000 | r | g | b); +} + +static FASTCALL CARD32 +fbFetchPixel_a4b4g4r4(const FbBits * bits, int offset, miIndexedPtr indexed) +{ + CARD32 pixel = ((CARD16 *) bits)[offset]; + + CARD32 a, r, g, b; + + a = ((pixel & 0xf000) | ((pixel & 0xf000) >> 4)) << 16; + b = ((pixel & 0x0f00) | ((pixel & 0x0f00) >> 4)) >> 4; + g = ((pixel & 0x00f0) | ((pixel & 0x00f0) >> 4)) << 8; + r = ((pixel & 0x000f) | ((pixel & 0x000f) << 4)) << 16; + return (a | r | g | b); +} + +static FASTCALL CARD32 +fbFetchPixel_x4b4g4r4(const FbBits * bits, int offset, miIndexedPtr indexed) +{ + CARD32 pixel = ((CARD16 *) bits)[offset]; + + CARD32 r, g, b; + + b = ((pixel & 0x0f00) | ((pixel & 0x0f00) >> 4)) >> 4; + g = ((pixel & 0x00f0) | ((pixel & 0x00f0) >> 4)) << 8; + r = ((pixel & 0x000f) | ((pixel & 0x000f) << 4)) << 16; + return (0xff000000 | r | g | b); +} + +static FASTCALL CARD32 +fbFetchPixel_a8(const FbBits * bits, int offset, miIndexedPtr indexed) +{ + CARD32 pixel = ((CARD8 *) bits)[offset]; + + return pixel << 24; +} + +static FASTCALL CARD32 +fbFetchPixel_r3g3b2(const FbBits * bits, int offset, miIndexedPtr indexed) +{ + CARD32 pixel = ((CARD8 *) bits)[offset]; + + CARD32 r, g, b; + + r = ((pixel & 0xe0) | ((pixel & 0xe0) >> 3) | ((pixel & 0xc0) >> 6)) << 16; + g = ((pixel & 0x1c) | ((pixel & 0x18) >> 3) | ((pixel & 0x1c) << 3)) << 8; + b = (((pixel & 0x03)) | + ((pixel & 0x03) << 2) | ((pixel & 0x03) << 4) | ((pixel & 0x03) << 6)); + return (0xff000000 | r | g | b); +} + +static FASTCALL CARD32 +fbFetchPixel_b2g3r3(const FbBits * bits, int offset, miIndexedPtr indexed) +{ + CARD32 pixel = ((CARD8 *) bits)[offset]; + + CARD32 r, g, b; + + b = (((pixel & 0xc0)) | + ((pixel & 0xc0) >> 2) | ((pixel & 0xc0) >> 4) | ((pixel & 0xc0) >> 6)); + g = ((pixel & 0x38) | ((pixel & 0x38) >> 3) | ((pixel & 0x30) << 2)) << 8; + r = (((pixel & 0x07)) | + ((pixel & 0x07) << 3) | ((pixel & 0x06) << 6)) << 16; + return (0xff000000 | r | g | b); +} + +static FASTCALL CARD32 +fbFetchPixel_a2r2g2b2(const FbBits * bits, int offset, miIndexedPtr indexed) +{ + CARD32 pixel = ((CARD8 *) bits)[offset]; + + CARD32 a, r, g, b; + + a = ((pixel & 0xc0) * 0x55) << 18; + r = ((pixel & 0x30) * 0x55) << 12; + g = ((pixel & 0x0c) * 0x55) << 6; + b = ((pixel & 0x03) * 0x55); + return a | r | g | b; +} + +static FASTCALL CARD32 +fbFetchPixel_a2b2g2r2(const FbBits * bits, int offset, miIndexedPtr indexed) +{ + CARD32 pixel = ((CARD8 *) bits)[offset]; + + CARD32 a, r, g, b; + + a = ((pixel & 0xc0) * 0x55) << 18; + b = ((pixel & 0x30) * 0x55) >> 6; + g = ((pixel & 0x0c) * 0x55) << 6; + r = ((pixel & 0x03) * 0x55) << 16; + return a | r | g | b; +} + +static FASTCALL CARD32 +fbFetchPixel_c8(const FbBits * bits, int offset, miIndexedPtr indexed) +{ + CARD32 pixel = ((CARD8 *) bits)[offset]; + + return indexed->rgba[pixel]; +} + +static FASTCALL CARD32 +fbFetchPixel_x4a4(const FbBits * bits, int offset, miIndexedPtr indexed) +{ + CARD32 pixel = ((CARD8 *) bits)[offset]; + + return ((pixel & 0xf) | ((pixel & 0xf) << 4)) << 24; +} + +#define Fetch8(l,o) (((CARD8 *) (l))[(o) >> 2]) +#if IMAGE_BYTE_ORDER == MSBFirst +#define Fetch4(l,o) ((o) & 2 ? Fetch8(l,o) & 0xf : Fetch8(l,o) >> 4) +#else +#define Fetch4(l,o) ((o) & 2 ? Fetch8(l,o) >> 4 : Fetch8(l,o) & 0xf) +#endif + +static FASTCALL CARD32 +fbFetchPixel_a4(const FbBits * bits, int offset, miIndexedPtr indexed) +{ + CARD32 pixel = Fetch4(bits, offset); + + pixel |= pixel << 4; + return pixel << 24; +} + +static FASTCALL CARD32 +fbFetchPixel_r1g2b1(const FbBits * bits, int offset, miIndexedPtr indexed) +{ + CARD32 pixel = Fetch4(bits, offset); + + CARD32 r, g, b; + + r = ((pixel & 0x8) * 0xff) << 13; + g = ((pixel & 0x6) * 0x55) << 7; + b = ((pixel & 0x1) * 0xff); + return 0xff000000 | r | g | b; +} + +static FASTCALL CARD32 +fbFetchPixel_b1g2r1(const FbBits * bits, int offset, miIndexedPtr indexed) +{ + CARD32 pixel = Fetch4(bits, offset); + + CARD32 r, g, b; + + b = ((pixel & 0x8) * 0xff) >> 3; + g = ((pixel & 0x6) * 0x55) << 7; + r = ((pixel & 0x1) * 0xff) << 16; + return 0xff000000 | r | g | b; +} + +static FASTCALL CARD32 +fbFetchPixel_a1r1g1b1(const FbBits * bits, int offset, miIndexedPtr indexed) +{ + CARD32 pixel = Fetch4(bits, offset); + + CARD32 a, r, g, b; + + a = ((pixel & 0x8) * 0xff) << 21; + r = ((pixel & 0x4) * 0xff) << 14; + g = ((pixel & 0x2) * 0xff) << 7; + b = ((pixel & 0x1) * 0xff); + return a | r | g | b; +} + +static FASTCALL CARD32 +fbFetchPixel_a1b1g1r1(const FbBits * bits, int offset, miIndexedPtr indexed) +{ + CARD32 pixel = Fetch4(bits, offset); + + CARD32 a, r, g, b; + + a = ((pixel & 0x8) * 0xff) << 21; + r = ((pixel & 0x4) * 0xff) >> 3; + g = ((pixel & 0x2) * 0xff) << 7; + b = ((pixel & 0x1) * 0xff) << 16; + return a | r | g | b; +} + +static FASTCALL CARD32 +fbFetchPixel_c4(const FbBits * bits, int offset, miIndexedPtr indexed) +{ + CARD32 pixel = Fetch4(bits, offset); + + return indexed->rgba[pixel]; +} + +static FASTCALL CARD32 +fbFetchPixel_a1(const FbBits * bits, int offset, miIndexedPtr indexed) +{ + CARD32 pixel = ((CARD32 *) bits)[offset >> 5]; + + CARD32 a; + +#if BITMAP_BIT_ORDER == MSBFirst + a = pixel >> (0x1f - (offset & 0x1f)); +#else + a = pixel >> (offset & 0x1f); +#endif + a = a & 1; + a |= a << 1; + a |= a << 2; + a |= a << 4; + return a << 24; +} + +static FASTCALL CARD32 +fbFetchPixel_g1(const FbBits * bits, int offset, miIndexedPtr indexed) +{ + CARD32 pixel = ((CARD32 *) bits)[offset >> 5]; + + CARD32 a; + +#if BITMAP_BIT_ORDER == MSBFirst + a = pixel >> (0x1f - (offset & 0x1f)); +#else + a = pixel >> (offset & 0x1f); +#endif + a = a & 1; + return indexed->rgba[a]; +} + +static fetchPixelProc +fetchPixelProcForPicture(PicturePtr pict) +{ + switch (pict->format) { + case PICT_a8r8g8b8: + return fbFetchPixel_a8r8g8b8; + case PICT_x8r8g8b8: + return fbFetchPixel_x8r8g8b8; + case PICT_a8b8g8r8: + return fbFetchPixel_a8b8g8r8; + case PICT_x8b8g8r8: + return fbFetchPixel_x8b8g8r8; + + /* 24bpp formats */ + case PICT_r8g8b8: + return fbFetchPixel_r8g8b8; + case PICT_b8g8r8: + return fbFetchPixel_b8g8r8; + + /* 16bpp formats */ + case PICT_r5g6b5: + return fbFetchPixel_r5g6b5; + case PICT_b5g6r5: + return fbFetchPixel_b5g6r5; + + case PICT_a1r5g5b5: + return fbFetchPixel_a1r5g5b5; + case PICT_x1r5g5b5: + return fbFetchPixel_x1r5g5b5; + case PICT_a1b5g5r5: + return fbFetchPixel_a1b5g5r5; + case PICT_x1b5g5r5: + return fbFetchPixel_x1b5g5r5; + case PICT_a4r4g4b4: + return fbFetchPixel_a4r4g4b4; + case PICT_x4r4g4b4: + return fbFetchPixel_x4r4g4b4; + case PICT_a4b4g4r4: + return fbFetchPixel_a4b4g4r4; + case PICT_x4b4g4r4: + return fbFetchPixel_x4b4g4r4; + + /* 8bpp formats */ + case PICT_a8: + return fbFetchPixel_a8; + case PICT_r3g3b2: + return fbFetchPixel_r3g3b2; + case PICT_b2g3r3: + return fbFetchPixel_b2g3r3; + case PICT_a2r2g2b2: + return fbFetchPixel_a2r2g2b2; + case PICT_a2b2g2r2: + return fbFetchPixel_a2b2g2r2; + case PICT_c8: + return fbFetchPixel_c8; + case PICT_g8: + return fbFetchPixel_c8; + case PICT_x4a4: + return fbFetchPixel_x4a4; + + /* 4bpp formats */ + case PICT_a4: + return fbFetchPixel_a4; + case PICT_r1g2b1: + return fbFetchPixel_r1g2b1; + case PICT_b1g2r1: + return fbFetchPixel_b1g2r1; + case PICT_a1r1g1b1: + return fbFetchPixel_a1r1g1b1; + case PICT_a1b1g1r1: + return fbFetchPixel_a1b1g1r1; + case PICT_c4: + return fbFetchPixel_c4; + case PICT_g4: + return fbFetchPixel_c4; + + /* 1bpp formats */ + case PICT_a1: + return fbFetchPixel_a1; + case PICT_g1: + return fbFetchPixel_g1; + } + + return NULL; +} + +/* + * All the store functions + */ + +typedef FASTCALL void (*storeProc) (FbBits * bits, const CARD32 *values, int x, + int width, miIndexedPtr indexed); + +#define Splita(v) CARD32 a = ((v) >> 24), r = ((v) >> 16) & 0xff, g = ((v) >> 8) & 0xff, b = (v) & 0xff +#define Split(v) CARD32 r = ((v) >> 16) & 0xff, g = ((v) >> 8) & 0xff, b = (v) & 0xff + +static FASTCALL void +fbStore_a8r8g8b8(FbBits * bits, const CARD32 *values, int x, int width, + miIndexedPtr indexed) +{ + memcpy(((CARD32 *) bits) + x, values, width * sizeof(CARD32)); +} + +static FASTCALL void +fbStore_x8r8g8b8(FbBits * bits, const CARD32 *values, int x, int width, + miIndexedPtr indexed) +{ + int i; + + CARD32 *pixel = (CARD32 *) bits + x; + + for (i = 0; i < width; ++i) + *pixel++ = values[i] & 0xffffff; +} + +static FASTCALL void +fbStore_a8b8g8r8(FbBits * bits, const CARD32 *values, int x, int width, + miIndexedPtr indexed) +{ + int i; + + CARD32 *pixel = (CARD32 *) bits + x; + + for (i = 0; i < width; ++i) + *pixel++ = + (values[i] & 0xff00ff00) | ((values[i] >> 16) & 0xff) | + ((values[i] & 0xff) << 16); +} + +static FASTCALL void +fbStore_x8b8g8r8(FbBits * bits, const CARD32 *values, int x, int width, + miIndexedPtr indexed) +{ + int i; + + CARD32 *pixel = (CARD32 *) bits + x; + + for (i = 0; i < width; ++i) + *pixel++ = + (values[i] & 0x0000ff00) | ((values[i] >> 16) & 0xff) | + ((values[i] & 0xff) << 16); +} + +static FASTCALL void +fbStore_r8g8b8(FbBits * bits, const CARD32 *values, int x, int width, + miIndexedPtr indexed) +{ + int i; + + CARD8 *pixel = ((CARD8 *) bits) + 3 * x; + + for (i = 0; i < width; ++i) { + Store24(pixel, values[i]); + pixel += 3; + } +} + +static FASTCALL void +fbStore_b8g8r8(FbBits * bits, const CARD32 *values, int x, int width, + miIndexedPtr indexed) +{ + int i; + + CARD8 *pixel = ((CARD8 *) bits) + 3 * x; + + for (i = 0; i < width; ++i) { +#if IMAGE_BYTE_ORDER == MSBFirst + *pixel++ = Blue(values[i]); + *pixel++ = Green(values[i]); + *pixel++ = Red(values[i]); +#else + *pixel++ = Red(values[i]); + *pixel++ = Green(values[i]); + *pixel++ = Blue(values[i]); +#endif + } +} + +static FASTCALL void +fbStore_r5g6b5(FbBits * bits, const CARD32 *values, int x, int width, + miIndexedPtr indexed) +{ + int i; + + CARD16 *pixel = ((CARD16 *) bits) + x; + + for (i = 0; i < width; ++i) { + CARD32 s = values[i]; + + *pixel++ = ((s >> 3) & 0x001f) | + ((s >> 5) & 0x07e0) | ((s >> 8) & 0xf800); + } +} + +static FASTCALL void +fbStore_b5g6r5(FbBits * bits, const CARD32 *values, int x, int width, + miIndexedPtr indexed) +{ + int i; + + CARD16 *pixel = ((CARD16 *) bits) + x; + + for (i = 0; i < width; ++i) { + Split(values[i]); + *pixel++ = (((b << 8) & 0xf800) | ((g << 3) & 0x07e0) | ((r >> 3))); + } +} + +static FASTCALL void +fbStore_a1r5g5b5(FbBits * bits, const CARD32 *values, int x, int width, + miIndexedPtr indexed) +{ + int i; + + CARD16 *pixel = ((CARD16 *) bits) + x; + + for (i = 0; i < width; ++i) { + Splita(values[i]); + *pixel++ = (((a << 8) & 0x8000) | + ((r << 7) & 0x7c00) | ((g << 2) & 0x03e0) | ((b >> 3))); + } +} + +static FASTCALL void +fbStore_x1r5g5b5(FbBits * bits, const CARD32 *values, int x, int width, + miIndexedPtr indexed) +{ + int i; + + CARD16 *pixel = ((CARD16 *) bits) + x; + + for (i = 0; i < width; ++i) { + Split(values[i]); + *pixel++ = (((r << 7) & 0x7c00) | ((g << 2) & 0x03e0) | ((b >> 3))); + } +} + +static FASTCALL void +fbStore_a1b5g5r5(FbBits * bits, const CARD32 *values, int x, int width, + miIndexedPtr indexed) +{ + int i; + + CARD16 *pixel = ((CARD16 *) bits) + x; + + for (i = 0; i < width; ++i) { + Splita(values[i]); + *pixel++ = (((a << 8) & 0x8000) | + ((b << 7) & 0x7c00) | ((g << 2) & 0x03e0) | ((r >> 3))); + } +} + +static FASTCALL void +fbStore_x1b5g5r5(FbBits * bits, const CARD32 *values, int x, int width, + miIndexedPtr indexed) +{ + int i; + + CARD16 *pixel = ((CARD16 *) bits) + x; + + for (i = 0; i < width; ++i) { + Split(values[i]); + *pixel++ = (((b << 7) & 0x7c00) | ((g << 2) & 0x03e0) | ((r >> 3))); + } +} + +static FASTCALL void +fbStore_a4r4g4b4(FbBits * bits, const CARD32 *values, int x, int width, + miIndexedPtr indexed) +{ + int i; + + CARD16 *pixel = ((CARD16 *) bits) + x; + + for (i = 0; i < width; ++i) { + Splita(values[i]); + *pixel++ = (((a << 8) & 0xf000) | + ((r << 4) & 0x0f00) | ((g) & 0x00f0) | ((b >> 4))); + } +} + +static FASTCALL void +fbStore_x4r4g4b4(FbBits * bits, const CARD32 *values, int x, int width, + miIndexedPtr indexed) +{ + int i; + + CARD16 *pixel = ((CARD16 *) bits) + x; + + for (i = 0; i < width; ++i) { + Split(values[i]); + *pixel++ = (((r << 4) & 0x0f00) | ((g) & 0x00f0) | ((b >> 4))); + } +} + +static FASTCALL void +fbStore_a4b4g4r4(FbBits * bits, const CARD32 *values, int x, int width, + miIndexedPtr indexed) +{ + int i; + + CARD16 *pixel = ((CARD16 *) bits) + x; + + for (i = 0; i < width; ++i) { + Splita(values[i]); + *pixel++ = (((a << 8) & 0xf000) | + ((b << 4) & 0x0f00) | ((g) & 0x00f0) | ((r >> 4))); + } +} + +static FASTCALL void +fbStore_x4b4g4r4(FbBits * bits, const CARD32 *values, int x, int width, + miIndexedPtr indexed) +{ + int i; + + CARD16 *pixel = ((CARD16 *) bits) + x; + + for (i = 0; i < width; ++i) { + Split(values[i]); + *pixel++ = (((b << 4) & 0x0f00) | ((g) & 0x00f0) | ((r >> 4))); + } +} + +static FASTCALL void +fbStore_a8(FbBits * bits, const CARD32 *values, int x, int width, + miIndexedPtr indexed) +{ + int i; + + CARD8 *pixel = ((CARD8 *) bits) + x; + + for (i = 0; i < width; ++i) { + *pixel++ = values[i] >> 24; + } +} + +static FASTCALL void +fbStore_r3g3b2(FbBits * bits, const CARD32 *values, int x, int width, + miIndexedPtr indexed) +{ + int i; + + CARD8 *pixel = ((CARD8 *) bits) + x; + + for (i = 0; i < width; ++i) { + Split(values[i]); + *pixel++ = (((r) & 0xe0) | ((g >> 3) & 0x1c) | ((b >> 6))); + } +} + +static FASTCALL void +fbStore_b2g3r3(FbBits * bits, const CARD32 *values, int x, int width, + miIndexedPtr indexed) +{ + int i; + + CARD8 *pixel = ((CARD8 *) bits) + x; + + for (i = 0; i < width; ++i) { + Split(values[i]); + *pixel++ = (((b) & 0xe0) | ((g >> 3) & 0x1c) | ((r >> 6))); + } +} + +static FASTCALL void +fbStore_a2r2g2b2(FbBits * bits, const CARD32 *values, int x, int width, + miIndexedPtr indexed) +{ + int i; + + CARD8 *pixel = ((CARD8 *) bits) + x; + + for (i = 0; i < width; ++i) { + Splita(values[i]); + *pixel++ = (((a) & 0xc0) | + ((r >> 2) & 0x30) | ((g >> 4) & 0x0c) | ((b >> 6))); + } +} + +static FASTCALL void +fbStore_c8(FbBits * bits, const CARD32 *values, int x, int width, + miIndexedPtr indexed) +{ + int i; + + CARD8 *pixel = ((CARD8 *) bits) + x; + + for (i = 0; i < width; ++i) { + *pixel++ = miIndexToEnt24(indexed, values[i]); + } +} + +static FASTCALL void +fbStore_x4a4(FbBits * bits, const CARD32 *values, int x, int width, + miIndexedPtr indexed) +{ + int i; + + CARD8 *pixel = ((CARD8 *) bits) + x; + + for (i = 0; i < width; ++i) { + *pixel++ = values[i] >> 28; + } +} + +#define Store8(l,o,v) (((CARD8 *) l)[(o) >> 3] = (v)) +#if IMAGE_BYTE_ORDER == MSBFirst +#define Store4(l,o,v) Store8(l,o,((o) & 4 ? \ + (Fetch8(l,o) & 0xf0) | (v) : \ + (Fetch8(l,o) & 0x0f) | ((v) << 4))) +#else +#define Store4(l,o,v) Store8(l,o,((o) & 4 ? \ + (Fetch8(l,o) & 0x0f) | ((v) << 4) : \ + (Fetch8(l,o) & 0xf0) | (v))) +#endif + +static FASTCALL void +fbStore_a4(FbBits * bits, const CARD32 *values, int x, int width, + miIndexedPtr indexed) +{ + int i; + + for (i = 0; i < width; ++i) { + Store4(bits, i + x, values[i] >> 28); + } +} + +static FASTCALL void +fbStore_r1g2b1(FbBits * bits, const CARD32 *values, int x, int width, + miIndexedPtr indexed) +{ + int i; + + for (i = 0; i < width; ++i) { + CARD32 pixel; + + Split(values[i]); + pixel = (((r >> 4) & 0x8) | ((g >> 5) & 0x6) | ((b >> 7))); + Store4(bits, i + x, pixel); + } +} + +static FASTCALL void +fbStore_b1g2r1(FbBits * bits, const CARD32 *values, int x, int width, + miIndexedPtr indexed) +{ + int i; + + for (i = 0; i < width; ++i) { + CARD32 pixel; + + Split(values[i]); + pixel = (((b >> 4) & 0x8) | ((g >> 5) & 0x6) | ((r >> 7))); + Store4(bits, i + x, pixel); + } +} + +static FASTCALL void +fbStore_a1r1g1b1(FbBits * bits, const CARD32 *values, int x, int width, + miIndexedPtr indexed) +{ + int i; + + for (i = 0; i < width; ++i) { + CARD32 pixel; + + Splita(values[i]); + pixel = (((a >> 4) & 0x8) | + ((r >> 5) & 0x4) | ((g >> 6) & 0x2) | ((b >> 7))); + Store4(bits, i + x, pixel); + } +} + +static FASTCALL void +fbStore_a1b1g1r1(FbBits * bits, const CARD32 *values, int x, int width, + miIndexedPtr indexed) +{ + int i; + + for (i = 0; i < width; ++i) { + CARD32 pixel; + + Splita(values[i]); + pixel = (((a >> 4) & 0x8) | + ((b >> 5) & 0x4) | ((g >> 6) & 0x2) | ((r >> 7))); + Store4(bits, i + x, pixel); + } +} + +static FASTCALL void +fbStore_c4(FbBits * bits, const CARD32 *values, int x, int width, + miIndexedPtr indexed) +{ + int i; + + for (i = 0; i < width; ++i) { + CARD32 pixel; + + pixel = miIndexToEnt24(indexed, values[i]); + Store4(bits, i + x, pixel); + } +} + +static FASTCALL void +fbStore_a1(FbBits * bits, const CARD32 *values, int x, int width, + miIndexedPtr indexed) +{ + int i; + + for (i = 0; i < width; ++i) { + CARD32 *pixel = ((CARD32 *) bits) + ((i + x) >> 5); + + CARD32 mask = FbStipMask((i + x) & 0x1f, 1); + + CARD32 v = values[i] & 0x80000000 ? mask : 0; + + *pixel = (*pixel & ~mask) | v; + } +} + +static FASTCALL void +fbStore_g1(FbBits * bits, const CARD32 *values, int x, int width, + miIndexedPtr indexed) +{ + int i; + + for (i = 0; i < width; ++i) { + CARD32 *pixel = ((CARD32 *) bits) + ((i + x) >> 5); + + CARD32 mask = FbStipMask((i + x) & 0x1f, 1); + + CARD32 v = miIndexToEntY24(indexed, values[i]) ? mask : 0; + + *pixel = (*pixel & ~mask) | v; + } +} + +static storeProc +storeProcForPicture(PicturePtr pict) +{ + switch (pict->format) { + case PICT_a8r8g8b8: + return fbStore_a8r8g8b8; + case PICT_x8r8g8b8: + return fbStore_x8r8g8b8; + case PICT_a8b8g8r8: + return fbStore_a8b8g8r8; + case PICT_x8b8g8r8: + return fbStore_x8b8g8r8; + + /* 24bpp formats */ + case PICT_r8g8b8: + return fbStore_r8g8b8; + case PICT_b8g8r8: + return fbStore_b8g8r8; + + /* 16bpp formats */ + case PICT_r5g6b5: + return fbStore_r5g6b5; + case PICT_b5g6r5: + return fbStore_b5g6r5; + + case PICT_a1r5g5b5: + return fbStore_a1r5g5b5; + case PICT_x1r5g5b5: + return fbStore_x1r5g5b5; + case PICT_a1b5g5r5: + return fbStore_a1b5g5r5; + case PICT_x1b5g5r5: + return fbStore_x1b5g5r5; + case PICT_a4r4g4b4: + return fbStore_a4r4g4b4; + case PICT_x4r4g4b4: + return fbStore_x4r4g4b4; + case PICT_a4b4g4r4: + return fbStore_a4b4g4r4; + case PICT_x4b4g4r4: + return fbStore_x4b4g4r4; + + /* 8bpp formats */ + case PICT_a8: + return fbStore_a8; + case PICT_r3g3b2: + return fbStore_r3g3b2; + case PICT_b2g3r3: + return fbStore_b2g3r3; + case PICT_a2r2g2b2: + return fbStore_a2r2g2b2; + case PICT_c8: + return fbStore_c8; + case PICT_g8: + return fbStore_c8; + case PICT_x4a4: + return fbStore_x4a4; + + /* 4bpp formats */ + case PICT_a4: + return fbStore_a4; + case PICT_r1g2b1: + return fbStore_r1g2b1; + case PICT_b1g2r1: + return fbStore_b1g2r1; + case PICT_a1r1g1b1: + return fbStore_a1r1g1b1; + case PICT_a1b1g1r1: + return fbStore_a1b1g1r1; + case PICT_c4: + return fbStore_c4; + case PICT_g4: + return fbStore_c4; + + /* 1bpp formats */ + case PICT_a1: + return fbStore_a1; + case PICT_g1: + return fbStore_g1; + default: + return NULL; + } +} + +/* + * Combine src and mask + */ +static FASTCALL void +fbCombineMaskU(CARD32 *src, const CARD32 *mask, int width) +{ + int i; + + for (i = 0; i < width; ++i) { + CARD32 a = mask[i] >> 24; + + CARD32 s = src[i]; + + FbByteMul(s, a); + src[i] = s; + } +} + +/* + * All of the composing functions + */ + +static FASTCALL void +fbCombineClear(CARD32 *dest, const CARD32 *src, int width) +{ + memset(dest, 0, width * sizeof(CARD32)); +} + +static FASTCALL void +fbCombineSrcU(CARD32 *dest, const CARD32 *src, int width) +{ + memcpy(dest, src, width * sizeof(CARD32)); +} + +static FASTCALL void +fbCombineOverU(CARD32 *dest, const CARD32 *src, int width) +{ + int i; + + for (i = 0; i < width; ++i) { + CARD32 s = src[i]; + + CARD32 d = dest[i]; + + CARD32 ia = Alpha(~s); + + FbByteMulAdd(d, ia, s); + dest[i] = d; + } +} + +static FASTCALL void +fbCombineOverReverseU(CARD32 *dest, const CARD32 *src, int width) +{ + int i; + + for (i = 0; i < width; ++i) { + CARD32 s = src[i]; + + CARD32 d = dest[i]; + + CARD32 ia = Alpha(~dest[i]); + + FbByteMulAdd(s, ia, d); + dest[i] = s; + } +} + +static FASTCALL void +fbCombineInU(CARD32 *dest, const CARD32 *src, int width) +{ + int i; + + for (i = 0; i < width; ++i) { + CARD32 s = src[i]; + + CARD32 a = Alpha(dest[i]); + + FbByteMul(s, a); + dest[i] = s; + } +} + +static FASTCALL void +fbCombineInReverseU(CARD32 *dest, const CARD32 *src, int width) +{ + int i; + + for (i = 0; i < width; ++i) { + CARD32 d = dest[i]; + + CARD32 a = Alpha(src[i]); + + FbByteMul(d, a); + dest[i] = d; + } +} + +static FASTCALL void +fbCombineOutU(CARD32 *dest, const CARD32 *src, int width) +{ + int i; + + for (i = 0; i < width; ++i) { + CARD32 s = src[i]; + + CARD32 a = Alpha(~dest[i]); + + FbByteMul(s, a); + dest[i] = s; + } +} + +static FASTCALL void +fbCombineOutReverseU(CARD32 *dest, const CARD32 *src, int width) +{ + int i; + + for (i = 0; i < width; ++i) { + CARD32 d = dest[i]; + + CARD32 a = Alpha(~src[i]); + + FbByteMul(d, a); + dest[i] = d; + } +} + +static FASTCALL void +fbCombineAtopU(CARD32 *dest, const CARD32 *src, int width) +{ + int i; + + for (i = 0; i < width; ++i) { + CARD32 s = src[i]; + + CARD32 d = dest[i]; + + CARD32 dest_a = Alpha(d); + + CARD32 src_ia = Alpha(~s); + + FbByteAddMul(s, dest_a, d, src_ia); + dest[i] = s; + } +} + +static FASTCALL void +fbCombineAtopReverseU(CARD32 *dest, const CARD32 *src, int width) +{ + int i; + + for (i = 0; i < width; ++i) { + CARD32 s = src[i]; + + CARD32 d = dest[i]; + + CARD32 src_a = Alpha(s); + + CARD32 dest_ia = Alpha(~d); + + FbByteAddMul(s, dest_ia, d, src_a); + dest[i] = s; + } +} + +static FASTCALL void +fbCombineXorU(CARD32 *dest, const CARD32 *src, int width) +{ + int i; + + for (i = 0; i < width; ++i) { + CARD32 s = src[i]; + + CARD32 d = dest[i]; + + CARD32 src_ia = Alpha(~s); + + CARD32 dest_ia = Alpha(~d); + + FbByteAddMul(s, dest_ia, d, src_ia); + dest[i] = s; + } +} + +static FASTCALL void +fbCombineAddU(CARD32 *dest, const CARD32 *src, int width) +{ + int i; + + for (i = 0; i < width; ++i) { + CARD32 s = src[i]; + + CARD32 d = dest[i]; + + FbByteAdd(d, s); + dest[i] = d; + } +} + +static FASTCALL void +fbCombineSaturateU(CARD32 *dest, const CARD32 *src, int width) +{ + int i; + + for (i = 0; i < width; ++i) { + CARD32 s = src[i]; + + CARD32 d = dest[i]; + + CARD16 sa, da; + + sa = s >> 24; + da = ~d >> 24; + if (sa > da) { + sa = FbIntDiv(da, sa); + FbByteMul(s, sa); + } + FbByteAdd(d, s); + dest[i] = d; + } +} + +/* + * All of the disjoint composing functions + + The four entries in the first column indicate what source contributions + come from each of the four areas of the picture -- areas covered by neither + A nor B, areas covered only by A, areas covered only by B and finally + areas covered by both A and B. + + Disjoint Conjoint + Fa Fb Fa Fb +(0,0,0,0) 0 0 0 0 +(0,A,0,A) 1 0 1 0 +(0,0,B,B) 0 1 0 1 +(0,A,B,A) 1 min((1-a)/b,1) 1 max(1-a/b,0) +(0,A,B,B) min((1-b)/a,1) 1 max(1-b/a,0) 1 +(0,0,0,A) max(1-(1-b)/a,0) 0 min(1,b/a) 0 +(0,0,0,B) 0 max(1-(1-a)/b,0) 0 min(a/b,1) +(0,A,0,0) min(1,(1-b)/a) 0 max(1-b/a,0) 0 +(0,0,B,0) 0 min(1,(1-a)/b) 0 max(1-a/b,0) +(0,0,B,A) max(1-(1-b)/a,0) min(1,(1-a)/b) min(1,b/a) max(1-a/b,0) +(0,A,0,B) min(1,(1-b)/a) max(1-(1-a)/b,0) max(1-b/a,0) min(1,a/b) +(0,A,B,0) min(1,(1-b)/a) min(1,(1-a)/b) max(1-b/a,0) max(1-a/b,0) + + */ + +#define CombineAOut 1 +#define CombineAIn 2 +#define CombineBOut 4 +#define CombineBIn 8 + +#define CombineClear 0 +#define CombineA (CombineAOut|CombineAIn) +#define CombineB (CombineBOut|CombineBIn) +#define CombineAOver (CombineAOut|CombineBOut|CombineAIn) +#define CombineBOver (CombineAOut|CombineBOut|CombineBIn) +#define CombineAAtop (CombineBOut|CombineAIn) +#define CombineBAtop (CombineAOut|CombineBIn) +#define CombineXor (CombineAOut|CombineBOut) + +/* portion covered by a but not b */ +static INLINE CARD8 +fbCombineDisjointOutPart(CARD8 a, CARD8 b) +{ + /* min (1, (1-b) / a) */ + + b = ~b; /* 1 - b */ + if (b >= a) /* 1 - b >= a -> (1-b)/a >= 1 */ + return 0xff; /* 1 */ + return FbIntDiv(b, a); /* (1-b) / a */ +} + +/* portion covered by both a and b */ +static INLINE CARD8 +fbCombineDisjointInPart(CARD8 a, CARD8 b) +{ + /* max (1-(1-b)/a,0) */ + /* = - min ((1-b)/a - 1, 0) */ + /* = 1 - min (1, (1-b)/a) */ + + b = ~b; /* 1 - b */ + if (b >= a) /* 1 - b >= a -> (1-b)/a >= 1 */ + return 0; /* 1 - 1 */ + return ~FbIntDiv(b, a); /* 1 - (1-b) / a */ +} + +static FASTCALL void +fbCombineDisjointGeneralU(CARD32 *dest, const CARD32 *src, int width, + CARD8 combine) +{ + int i; + + for (i = 0; i < width; ++i) { + CARD32 s = src[i]; + + CARD32 d = dest[i]; + + CARD32 m, n, o, p; + + CARD16 Fa, Fb, t, u, v; + + CARD8 sa = s >> 24; + + CARD8 da = d >> 24; + + switch (combine & CombineA) { + default: + Fa = 0; + break; + case CombineAOut: + Fa = fbCombineDisjointOutPart(sa, da); + break; + case CombineAIn: + Fa = fbCombineDisjointInPart(sa, da); + break; + case CombineA: + Fa = 0xff; + break; + } + + switch (combine & CombineB) { + default: + Fb = 0; + break; + case CombineBOut: + Fb = fbCombineDisjointOutPart(da, sa); + break; + case CombineBIn: + Fb = fbCombineDisjointInPart(da, sa); + break; + case CombineB: + Fb = 0xff; + break; + } + m = FbGen(s, d, 0, Fa, Fb, t, u, v); + n = FbGen(s, d, 8, Fa, Fb, t, u, v); + o = FbGen(s, d, 16, Fa, Fb, t, u, v); + p = FbGen(s, d, 24, Fa, Fb, t, u, v); + s = m | n | o | p; + dest[i] = s; + } +} + +static FASTCALL void +fbCombineDisjointOverU(CARD32 *dest, const CARD32 *src, int width) +{ + int i; + + for (i = 0; i < width; ++i) { + CARD32 s = src[i]; + + CARD16 a = s >> 24; + + if (a != 0x00) { + if (a != 0xff) { + CARD32 d = dest[i]; + + a = fbCombineDisjointOutPart(d >> 24, a); + FbByteMulAdd(d, a, s); + s = d; + } + dest[i] = s; + } + } +} + +static FASTCALL void +fbCombineDisjointInU(CARD32 *dest, const CARD32 *src, int width) +{ + fbCombineDisjointGeneralU(dest, src, width, CombineAIn); +} + +static FASTCALL void +fbCombineDisjointInReverseU(CARD32 *dest, const CARD32 *src, int width) +{ + fbCombineDisjointGeneralU(dest, src, width, CombineBIn); +} + +static FASTCALL void +fbCombineDisjointOutU(CARD32 *dest, const CARD32 *src, int width) +{ + fbCombineDisjointGeneralU(dest, src, width, CombineAOut); +} + +static FASTCALL void +fbCombineDisjointOutReverseU(CARD32 *dest, const CARD32 *src, int width) +{ + fbCombineDisjointGeneralU(dest, src, width, CombineBOut); +} + +static FASTCALL void +fbCombineDisjointAtopU(CARD32 *dest, const CARD32 *src, int width) +{ + fbCombineDisjointGeneralU(dest, src, width, CombineAAtop); +} + +static FASTCALL void +fbCombineDisjointAtopReverseU(CARD32 *dest, const CARD32 *src, int width) +{ + fbCombineDisjointGeneralU(dest, src, width, CombineBAtop); +} + +static FASTCALL void +fbCombineDisjointXorU(CARD32 *dest, const CARD32 *src, int width) +{ + fbCombineDisjointGeneralU(dest, src, width, CombineXor); +} + +/* portion covered by a but not b */ +static INLINE CARD8 +fbCombineConjointOutPart(CARD8 a, CARD8 b) +{ + /* max (1-b/a,0) */ + /* = 1-min(b/a,1) */ + + /* min (1, (1-b) / a) */ + + if (b >= a) /* b >= a -> b/a >= 1 */ + return 0x00; /* 0 */ + return ~FbIntDiv(b, a); /* 1 - b/a */ +} + +/* portion covered by both a and b */ +static INLINE CARD8 +fbCombineConjointInPart(CARD8 a, CARD8 b) +{ + /* min (1,b/a) */ + + if (b >= a) /* b >= a -> b/a >= 1 */ + return 0xff; /* 1 */ + return FbIntDiv(b, a); /* b/a */ +} + +static FASTCALL void +fbCombineConjointGeneralU(CARD32 *dest, const CARD32 *src, int width, + CARD8 combine) +{ + int i; + + for (i = 0; i < width; ++i) { + CARD32 s = src[i]; + + CARD32 d = dest[i]; + + CARD32 m, n, o, p; + + CARD16 Fa, Fb, t, u, v; + + CARD8 sa = s >> 24; + + CARD8 da = d >> 24; + + switch (combine & CombineA) { + default: + Fa = 0; + break; + case CombineAOut: + Fa = fbCombineConjointOutPart(sa, da); + break; + case CombineAIn: + Fa = fbCombineConjointInPart(sa, da); + break; + case CombineA: + Fa = 0xff; + break; + } + + switch (combine & CombineB) { + default: + Fb = 0; + break; + case CombineBOut: + Fb = fbCombineConjointOutPart(da, sa); + break; + case CombineBIn: + Fb = fbCombineConjointInPart(da, sa); + break; + case CombineB: + Fb = 0xff; + break; + } + m = FbGen(s, d, 0, Fa, Fb, t, u, v); + n = FbGen(s, d, 8, Fa, Fb, t, u, v); + o = FbGen(s, d, 16, Fa, Fb, t, u, v); + p = FbGen(s, d, 24, Fa, Fb, t, u, v); + s = m | n | o | p; + dest[i] = s; + } +} + +static FASTCALL void +fbCombineConjointOverU(CARD32 *dest, const CARD32 *src, int width) +{ + fbCombineConjointGeneralU(dest, src, width, CombineAOver); +} + +static FASTCALL void +fbCombineConjointOverReverseU(CARD32 *dest, const CARD32 *src, int width) +{ + fbCombineConjointGeneralU(dest, src, width, CombineBOver); +} + +static FASTCALL void +fbCombineConjointInU(CARD32 *dest, const CARD32 *src, int width) +{ + fbCombineConjointGeneralU(dest, src, width, CombineAIn); +} + +static FASTCALL void +fbCombineConjointInReverseU(CARD32 *dest, const CARD32 *src, int width) +{ + fbCombineConjointGeneralU(dest, src, width, CombineBIn); +} + +static FASTCALL void +fbCombineConjointOutU(CARD32 *dest, const CARD32 *src, int width) +{ + fbCombineConjointGeneralU(dest, src, width, CombineAOut); +} + +static FASTCALL void +fbCombineConjointOutReverseU(CARD32 *dest, const CARD32 *src, int width) +{ + fbCombineConjointGeneralU(dest, src, width, CombineBOut); +} + +static FASTCALL void +fbCombineConjointAtopU(CARD32 *dest, const CARD32 *src, int width) +{ + fbCombineConjointGeneralU(dest, src, width, CombineAAtop); +} + +static FASTCALL void +fbCombineConjointAtopReverseU(CARD32 *dest, const CARD32 *src, int width) +{ + fbCombineConjointGeneralU(dest, src, width, CombineBAtop); +} + +static FASTCALL void +fbCombineConjointXorU(CARD32 *dest, const CARD32 *src, int width) +{ + fbCombineConjointGeneralU(dest, src, width, CombineXor); +} + +static const CombineFuncU fbCombineFuncU[] = { + fbCombineClear, + fbCombineSrcU, + NULL, /* CombineDst */ + fbCombineOverU, + fbCombineOverReverseU, + fbCombineInU, + fbCombineInReverseU, + fbCombineOutU, + fbCombineOutReverseU, + fbCombineAtopU, + fbCombineAtopReverseU, + fbCombineXorU, + fbCombineAddU, + fbCombineSaturateU, + NULL, + NULL, + fbCombineClear, + fbCombineSrcU, + NULL, /* CombineDst */ + fbCombineDisjointOverU, + fbCombineSaturateU, /* DisjointOverReverse */ + fbCombineDisjointInU, + fbCombineDisjointInReverseU, + fbCombineDisjointOutU, + fbCombineDisjointOutReverseU, + fbCombineDisjointAtopU, + fbCombineDisjointAtopReverseU, + fbCombineDisjointXorU, + NULL, + NULL, + NULL, + NULL, + fbCombineClear, + fbCombineSrcU, + NULL, /* CombineDst */ + fbCombineConjointOverU, + fbCombineConjointOverReverseU, + fbCombineConjointInU, + fbCombineConjointInReverseU, + fbCombineConjointOutU, + fbCombineConjointOutReverseU, + fbCombineConjointAtopU, + fbCombineConjointAtopReverseU, + fbCombineConjointXorU, +}; + +static FASTCALL void +fbCombineMaskC(CARD32 *src, CARD32 *mask, int width) +{ + int i; + + for (i = 0; i < width; ++i) { + CARD32 a = mask[i]; + + CARD32 x; + + CARD16 xa; + + if (!a) { + src[i] = 0; + continue; + } + + x = src[i]; + if (a == 0xffffffff) { + x = x >> 24; + x |= x << 8; + x |= x << 16; + mask[i] = x; + continue; + } + + xa = x >> 24; + FbByteMulC(x, a); + src[i] = x; + FbByteMul(a, xa); + mask[i] = a; + } +} + +static FASTCALL void +fbCombineMaskValueC(CARD32 *src, const CARD32 *mask, int width) +{ + int i; + + for (i = 0; i < width; ++i) { + CARD32 a = mask[i]; + + CARD32 x; + + if (!a) { + src[i] = 0; + continue; + } + + if (a == 0xffffffff) + continue; + + x = src[i]; + FbByteMulC(x, a); + src[i] = x; + } +} + +static FASTCALL void +fbCombineMaskAlphaC(const CARD32 *src, CARD32 *mask, int width) +{ + int i; + + for (i = 0; i < width; ++i) { + CARD32 a = mask[i]; + + CARD32 x; + + if (!a) + continue; + + x = src[i] >> 24; + if (x == 0xff) + continue; + if (a == 0xffffffff) { + x = x >> 24; + x |= x << 8; + x |= x << 16; + mask[i] = x; + continue; + } + + FbByteMul(a, x); + mask[i] = a; + } +} + +static FASTCALL void +fbCombineClearC(CARD32 *dest, CARD32 *src, CARD32 *mask, int width) +{ + memset(dest, 0, width * sizeof(CARD32)); +} + +static FASTCALL void +fbCombineSrcC(CARD32 *dest, CARD32 *src, CARD32 *mask, int width) +{ + fbCombineMaskValueC(src, mask, width); + memcpy(dest, src, width * sizeof(CARD32)); +} + +static FASTCALL void +fbCombineOverC(CARD32 *dest, CARD32 *src, CARD32 *mask, int width) +{ + int i; + + fbCombineMaskC(src, mask, width); + for (i = 0; i < width; ++i) { + CARD32 s = src[i]; + + CARD32 a = ~mask[i]; + + if (a != 0xffffffff) { + if (a) { + CARD32 d = dest[i]; + + FbByteMulAddC(d, a, s); + s = d; + } + dest[i] = s; + } + } +} + +static FASTCALL void +fbCombineOverReverseC(CARD32 *dest, CARD32 *src, CARD32 *mask, int width) +{ + int i; + + fbCombineMaskValueC(src, mask, width); + for (i = 0; i < width; ++i) { + CARD32 d = dest[i]; + + CARD32 a = ~d >> 24; + + if (a) { + CARD32 s = src[i]; + + if (a != 0xff) { + FbByteMulAdd(s, a, d); + } + dest[i] = s; + } + } +} + +static FASTCALL void +fbCombineInC(CARD32 *dest, CARD32 *src, CARD32 *mask, int width) +{ + int i; + + fbCombineMaskValueC(src, mask, width); + for (i = 0; i < width; ++i) { + CARD32 d = dest[i]; + + CARD16 a = d >> 24; + + CARD32 s = 0; + + if (a) { + s = src[i]; + if (a != 0xff) { + FbByteMul(s, a); + } + } + dest[i] = s; + } +} + +static FASTCALL void +fbCombineInReverseC(CARD32 *dest, CARD32 *src, CARD32 *mask, int width) +{ + int i; + + fbCombineMaskAlphaC(src, mask, width); + for (i = 0; i < width; ++i) { + CARD32 a = mask[i]; + + if (a != 0xffffffff) { + CARD32 d = 0; + + if (a) { + d = dest[i]; + FbByteMulC(d, a); + } + dest[i] = d; + } + } +} + +static FASTCALL void +fbCombineOutC(CARD32 *dest, CARD32 *src, CARD32 *mask, int width) +{ + int i; + + fbCombineMaskValueC(src, mask, width); + for (i = 0; i < width; ++i) { + CARD32 d = dest[i]; + + CARD16 a = ~d >> 24; + + CARD32 s = 0; + + if (a) { + s = src[i]; + if (a != 0xff) { + FbByteMul(s, a); + } + } + dest[i] = s; + } +} + +static FASTCALL void +fbCombineOutReverseC(CARD32 *dest, CARD32 *src, CARD32 *mask, int width) +{ + int i; + + fbCombineMaskAlphaC(src, mask, width); + for (i = 0; i < width; ++i) { + CARD32 a = ~mask[i]; + + if (a != 0xffffffff) { + CARD32 d = 0; + + if (a) { + d = dest[i]; + FbByteMulC(d, a); + } + dest[i] = d; + } + } +} + +static FASTCALL void +fbCombineAtopC(CARD32 *dest, CARD32 *src, CARD32 *mask, int width) +{ + int i; + + fbCombineMaskC(src, mask, width); + for (i = 0; i < width; ++i) { + CARD32 d = dest[i]; + + CARD32 s = src[i]; + + CARD32 ad = ~mask[i]; + + CARD16 as = d >> 24; + + FbByteAddMulC(d, ad, s, as); + dest[i] = d; + } +} + +static FASTCALL void +fbCombineAtopReverseC(CARD32 *dest, CARD32 *src, CARD32 *mask, int width) +{ + int i; + + fbCombineMaskC(src, mask, width); + for (i = 0; i < width; ++i) { + + CARD32 d = dest[i]; + + CARD32 s = src[i]; + + CARD32 ad = mask[i]; + + CARD16 as = ~d >> 24; + + FbByteAddMulC(d, ad, s, as); + dest[i] = d; + } +} + +static FASTCALL void +fbCombineXorC(CARD32 *dest, CARD32 *src, CARD32 *mask, int width) +{ + int i; + + fbCombineMaskC(src, mask, width); + for (i = 0; i < width; ++i) { + CARD32 d = dest[i]; + + CARD32 s = src[i]; + + CARD32 ad = ~mask[i]; + + CARD16 as = ~d >> 24; + + FbByteAddMulC(d, ad, s, as); + dest[i] = d; + } +} + +static FASTCALL void +fbCombineAddC(CARD32 *dest, CARD32 *src, CARD32 *mask, int width) +{ + int i; + + fbCombineMaskValueC(src, mask, width); + for (i = 0; i < width; ++i) { + CARD32 s = src[i]; + + CARD32 d = dest[i]; + + FbByteAdd(d, s); + dest[i] = d; + } +} + +static FASTCALL void +fbCombineSaturateC(CARD32 *dest, CARD32 *src, CARD32 *mask, int width) +{ + int i; + + fbCombineMaskC(src, mask, width); + for (i = 0; i < width; ++i) { + CARD32 s, d; + + CARD16 sa, sr, sg, sb, da; + + CARD16 t, u, v; + + CARD32 m, n, o, p; + + d = dest[i]; + s = src[i]; + sa = (mask[i] >> 24); + sr = (mask[i] >> 16) & 0xff; + sg = (mask[i] >> 8) & 0xff; + sb = (mask[i]) & 0xff; + da = ~d >> 24; + + if (sb <= da) + m = FbAdd(s, d, 0, t); + else + m = FbGen(s, d, 0, (da << 8) / sb, 0xff, t, u, v); + + if (sg <= da) + n = FbAdd(s, d, 8, t); + else + n = FbGen(s, d, 8, (da << 8) / sg, 0xff, t, u, v); + + if (sr <= da) + o = FbAdd(s, d, 16, t); + else + o = FbGen(s, d, 16, (da << 8) / sr, 0xff, t, u, v); + + if (sa <= da) + p = FbAdd(s, d, 24, t); + else + p = FbGen(s, d, 24, (da << 8) / sa, 0xff, t, u, v); + + dest[i] = m | n | o | p; + } +} + +static FASTCALL void +fbCombineDisjointGeneralC(CARD32 *dest, CARD32 *src, CARD32 *mask, int width, + CARD8 combine) +{ + int i; + + fbCombineMaskC(src, mask, width); + for (i = 0; i < width; ++i) { + CARD32 s, d; + + CARD32 m, n, o, p; + + CARD32 Fa, Fb; + + CARD16 t, u, v; + + CARD32 sa; + + CARD8 da; + + s = src[i]; + sa = mask[i]; + d = dest[i]; + da = d >> 24; + + switch (combine & CombineA) { + default: + Fa = 0; + break; + case CombineAOut: + m = fbCombineDisjointOutPart((CARD8) (sa >> 0), da); + n = fbCombineDisjointOutPart((CARD8) (sa >> 8), da) << 8; + o = fbCombineDisjointOutPart((CARD8) (sa >> 16), da) << 16; + p = fbCombineDisjointOutPart((CARD8) (sa >> 24), da) << 24; + Fa = m | n | o | p; + break; + case CombineAIn: + m = fbCombineDisjointInPart((CARD8) (sa >> 0), da); + n = fbCombineDisjointInPart((CARD8) (sa >> 8), da) << 8; + o = fbCombineDisjointInPart((CARD8) (sa >> 16), da) << 16; + p = fbCombineDisjointInPart((CARD8) (sa >> 24), da) << 24; + Fa = m | n | o | p; + break; + case CombineA: + Fa = 0xffffffff; + break; + } + + switch (combine & CombineB) { + default: + Fb = 0; + break; + case CombineBOut: + m = fbCombineDisjointOutPart(da, (CARD8) (sa >> 0)); + n = fbCombineDisjointOutPart(da, (CARD8) (sa >> 8)) << 8; + o = fbCombineDisjointOutPart(da, (CARD8) (sa >> 16)) << 16; + p = fbCombineDisjointOutPart(da, (CARD8) (sa >> 24)) << 24; + Fb = m | n | o | p; + break; + case CombineBIn: + m = fbCombineDisjointInPart(da, (CARD8) (sa >> 0)); + n = fbCombineDisjointInPart(da, (CARD8) (sa >> 8)) << 8; + o = fbCombineDisjointInPart(da, (CARD8) (sa >> 16)) << 16; + p = fbCombineDisjointInPart(da, (CARD8) (sa >> 24)) << 24; + Fb = m | n | o | p; + break; + case CombineB: + Fb = 0xffffffff; + break; + } + m = FbGen(s, d, 0, FbGet8(Fa, 0), FbGet8(Fb, 0), t, u, v); + n = FbGen(s, d, 8, FbGet8(Fa, 8), FbGet8(Fb, 8), t, u, v); + o = FbGen(s, d, 16, FbGet8(Fa, 16), FbGet8(Fb, 16), t, u, v); + p = FbGen(s, d, 24, FbGet8(Fa, 24), FbGet8(Fb, 24), t, u, v); + s = m | n | o | p; + dest[i] = s; + } +} + +static FASTCALL void +fbCombineDisjointOverC(CARD32 *dest, CARD32 *src, CARD32 *mask, int width) +{ + fbCombineDisjointGeneralC(dest, src, mask, width, CombineAOver); +} + +static FASTCALL void +fbCombineDisjointInC(CARD32 *dest, CARD32 *src, CARD32 *mask, int width) +{ + fbCombineDisjointGeneralC(dest, src, mask, width, CombineAIn); +} + +static FASTCALL void +fbCombineDisjointInReverseC(CARD32 *dest, CARD32 *src, CARD32 *mask, int width) +{ + fbCombineDisjointGeneralC(dest, src, mask, width, CombineBIn); +} + +static FASTCALL void +fbCombineDisjointOutC(CARD32 *dest, CARD32 *src, CARD32 *mask, int width) +{ + fbCombineDisjointGeneralC(dest, src, mask, width, CombineAOut); +} + +static FASTCALL void +fbCombineDisjointOutReverseC(CARD32 *dest, CARD32 *src, CARD32 *mask, int width) +{ + fbCombineDisjointGeneralC(dest, src, mask, width, CombineBOut); +} + +static FASTCALL void +fbCombineDisjointAtopC(CARD32 *dest, CARD32 *src, CARD32 *mask, int width) +{ + fbCombineDisjointGeneralC(dest, src, mask, width, CombineAAtop); +} + +static FASTCALL void +fbCombineDisjointAtopReverseC(CARD32 *dest, CARD32 *src, CARD32 *mask, + int width) +{ + fbCombineDisjointGeneralC(dest, src, mask, width, CombineBAtop); +} + +static FASTCALL void +fbCombineDisjointXorC(CARD32 *dest, CARD32 *src, CARD32 *mask, int width) +{ + fbCombineDisjointGeneralC(dest, src, mask, width, CombineXor); +} + +static FASTCALL void +fbCombineConjointGeneralC(CARD32 *dest, CARD32 *src, CARD32 *mask, int width, + CARD8 combine) +{ + int i; + + fbCombineMaskC(src, mask, width); + for (i = 0; i < width; ++i) { + CARD32 s, d; + + CARD32 m, n, o, p; + + CARD32 Fa, Fb; + + CARD16 t, u, v; + + CARD32 sa; + + CARD8 da; + + s = src[i]; + sa = mask[i]; + d = dest[i]; + da = d >> 24; + + switch (combine & CombineA) { + default: + Fa = 0; + break; + case CombineAOut: + m = fbCombineConjointOutPart((CARD8) (sa >> 0), da); + n = fbCombineConjointOutPart((CARD8) (sa >> 8), da) << 8; + o = fbCombineConjointOutPart((CARD8) (sa >> 16), da) << 16; + p = fbCombineConjointOutPart((CARD8) (sa >> 24), da) << 24; + Fa = m | n | o | p; + break; + case CombineAIn: + m = fbCombineConjointInPart((CARD8) (sa >> 0), da); + n = fbCombineConjointInPart((CARD8) (sa >> 8), da) << 8; + o = fbCombineConjointInPart((CARD8) (sa >> 16), da) << 16; + p = fbCombineConjointInPart((CARD8) (sa >> 24), da) << 24; + Fa = m | n | o | p; + break; + case CombineA: + Fa = 0xffffffff; + break; + } + + switch (combine & CombineB) { + default: + Fb = 0; + break; + case CombineBOut: + m = fbCombineConjointOutPart(da, (CARD8) (sa >> 0)); + n = fbCombineConjointOutPart(da, (CARD8) (sa >> 8)) << 8; + o = fbCombineConjointOutPart(da, (CARD8) (sa >> 16)) << 16; + p = fbCombineConjointOutPart(da, (CARD8) (sa >> 24)) << 24; + Fb = m | n | o | p; + break; + case CombineBIn: + m = fbCombineConjointInPart(da, (CARD8) (sa >> 0)); + n = fbCombineConjointInPart(da, (CARD8) (sa >> 8)) << 8; + o = fbCombineConjointInPart(da, (CARD8) (sa >> 16)) << 16; + p = fbCombineConjointInPart(da, (CARD8) (sa >> 24)) << 24; + Fb = m | n | o | p; + break; + case CombineB: + Fb = 0xffffffff; + break; + } + m = FbGen(s, d, 0, FbGet8(Fa, 0), FbGet8(Fb, 0), t, u, v); + n = FbGen(s, d, 8, FbGet8(Fa, 8), FbGet8(Fb, 8), t, u, v); + o = FbGen(s, d, 16, FbGet8(Fa, 16), FbGet8(Fb, 16), t, u, v); + p = FbGen(s, d, 24, FbGet8(Fa, 24), FbGet8(Fb, 24), t, u, v); + s = m | n | o | p; + dest[i] = s; + } +} + +static FASTCALL void +fbCombineConjointOverC(CARD32 *dest, CARD32 *src, CARD32 *mask, int width) +{ + fbCombineConjointGeneralC(dest, src, mask, width, CombineAOver); +} + +static FASTCALL void +fbCombineConjointOverReverseC(CARD32 *dest, CARD32 *src, CARD32 *mask, + int width) +{ + fbCombineConjointGeneralC(dest, src, mask, width, CombineBOver); +} + +static FASTCALL void +fbCombineConjointInC(CARD32 *dest, CARD32 *src, CARD32 *mask, int width) +{ + fbCombineConjointGeneralC(dest, src, mask, width, CombineAIn); +} + +static FASTCALL void +fbCombineConjointInReverseC(CARD32 *dest, CARD32 *src, CARD32 *mask, int width) +{ + fbCombineConjointGeneralC(dest, src, mask, width, CombineBIn); +} + +static FASTCALL void +fbCombineConjointOutC(CARD32 *dest, CARD32 *src, CARD32 *mask, int width) +{ + fbCombineConjointGeneralC(dest, src, mask, width, CombineAOut); +} + +static FASTCALL void +fbCombineConjointOutReverseC(CARD32 *dest, CARD32 *src, CARD32 *mask, int width) +{ + fbCombineConjointGeneralC(dest, src, mask, width, CombineBOut); +} + +static FASTCALL void +fbCombineConjointAtopC(CARD32 *dest, CARD32 *src, CARD32 *mask, int width) +{ + fbCombineConjointGeneralC(dest, src, mask, width, CombineAAtop); +} + +static FASTCALL void +fbCombineConjointAtopReverseC(CARD32 *dest, CARD32 *src, CARD32 *mask, + int width) +{ + fbCombineConjointGeneralC(dest, src, mask, width, CombineBAtop); +} + +static FASTCALL void +fbCombineConjointXorC(CARD32 *dest, CARD32 *src, CARD32 *mask, int width) +{ + fbCombineConjointGeneralC(dest, src, mask, width, CombineXor); +} + +static const CombineFuncC fbCombineFuncC[] = { + fbCombineClearC, + fbCombineSrcC, + NULL, /* Dest */ + fbCombineOverC, + fbCombineOverReverseC, + fbCombineInC, + fbCombineInReverseC, + fbCombineOutC, + fbCombineOutReverseC, + fbCombineAtopC, + fbCombineAtopReverseC, + fbCombineXorC, + fbCombineAddC, + fbCombineSaturateC, + NULL, + NULL, + fbCombineClearC, /* 0x10 */ + fbCombineSrcC, + NULL, /* Dest */ + fbCombineDisjointOverC, + fbCombineSaturateC, /* DisjointOverReverse */ + fbCombineDisjointInC, + fbCombineDisjointInReverseC, + fbCombineDisjointOutC, + fbCombineDisjointOutReverseC, + fbCombineDisjointAtopC, + fbCombineDisjointAtopReverseC, + fbCombineDisjointXorC, /* 0x1b */ + NULL, + NULL, + NULL, + NULL, + fbCombineClearC, + fbCombineSrcC, + NULL, /* Dest */ + fbCombineConjointOverC, + fbCombineConjointOverReverseC, + fbCombineConjointInC, + fbCombineConjointInReverseC, + fbCombineConjointOutC, + fbCombineConjointOutReverseC, + fbCombineConjointAtopC, + fbCombineConjointAtopReverseC, + fbCombineConjointXorC, +}; + +static const FbComposeFunctions composeFunctions = { + fbCombineFuncU, + fbCombineFuncC, + fbCombineMaskU +}; + +static void +fbFetchSolid(PicturePtr pict, int x, int y, int width, CARD32 *buffer) +{ + FbBits *bits; + + FbStride stride; + + int bpp; + + int xoff, yoff; + + CARD32 color; + + CARD32 *end; + + fetchPixelProc fetch = fetchPixelProcForPicture(pict); + + miIndexedPtr indexed = (miIndexedPtr) pict->pFormat->index.devPrivate; + + fbGetDrawable(pict->pDrawable, bits, stride, bpp, xoff, yoff); + bits += yoff * stride + (xoff * bpp >> FB_SHIFT); + + color = fetch(bits, 0, indexed); + + end = buffer + width; + while (buffer < end) + *buffer++ = color; +} + +static void +fbFetch(PicturePtr pict, int x, int y, int width, CARD32 *buffer) +{ + FbBits *bits; + + FbStride stride; + + int bpp; + + int xoff, yoff; + + fetchProc fetch = fetchProcForPicture(pict); + + miIndexedPtr indexed = (miIndexedPtr) pict->pFormat->index.devPrivate; + + fbGetDrawable(pict->pDrawable, bits, stride, bpp, xoff, yoff); + x += xoff; + y += yoff; + + bits += y * stride; + + fetch(bits, x, width, buffer, indexed); +} + +#define MOD(a,b) ((a) < 0 ? ((b) - ((-(a) - 1) % (b))) - 1 : (a) % (b)) +#define DIV(a,b) ((((a) < 0) == ((b) < 0)) ? (a) / (b) :\ + ((a) - (b) + 1 - (((b) < 0) << 1)) / (b)) + +static CARD32 +gradientPixel(const SourcePictPtr pGradient, xFixed_48_16 pos, + unsigned int spread) +{ + int ipos = (pos * PICT_GRADIENT_STOPTABLE_SIZE - 1) >> 16; + + /* calculate the actual offset. */ + if (ipos < 0 || ipos >= PICT_GRADIENT_STOPTABLE_SIZE) { + if (pGradient->type == SourcePictTypeConical || spread == RepeatNormal) { + ipos = ipos % PICT_GRADIENT_STOPTABLE_SIZE; + ipos = ipos < 0 ? PICT_GRADIENT_STOPTABLE_SIZE + ipos : ipos; + + } + else if (spread == RepeatReflect) { + const int limit = PICT_GRADIENT_STOPTABLE_SIZE * 2 - 1; + + ipos = ipos % limit; + ipos = ipos < 0 ? limit + ipos : ipos; + ipos = ipos >= PICT_GRADIENT_STOPTABLE_SIZE ? limit - ipos : ipos; + + } + else if (spread == RepeatPad) { + if (ipos < 0) + ipos = 0; + else if (ipos >= PICT_GRADIENT_STOPTABLE_SIZE) + ipos = PICT_GRADIENT_STOPTABLE_SIZE - 1; + } + else { /* RepeatNone */ + return 0; + } + } + + assert(ipos >= 0); + assert(ipos < PICT_GRADIENT_STOPTABLE_SIZE); + + return pGradient->linear.colorTable[ipos]; +} + +static void +fbFetchSourcePict(PicturePtr pict, int x, int y, int width, CARD32 *buffer) +{ + SourcePictPtr pGradient = pict->pSourcePict; + + CARD32 *end = buffer + width; + + if (pGradient->type == SourcePictTypeSolidFill) { + CARD32 color = pGradient->solidFill.color; + + while (buffer < end) { + *buffer++ = color; + } + } + else if (pGradient->type == SourcePictTypeLinear) { + PictVector v, unit; + + xFixed_32_32 l; + + xFixed_48_16 dx, dy, a, b, off; + + /* reference point is the center of the pixel */ + v.vector[0] = IntToxFixed(x) + xFixed1 / 2; + v.vector[1] = IntToxFixed(y) + xFixed1 / 2; + v.vector[2] = xFixed1; + if (pict->transform) { + if (!PictureTransformPoint3d(pict->transform, &v)) + return; + unit.vector[0] = pict->transform->matrix[0][0]; + unit.vector[1] = pict->transform->matrix[1][0]; + unit.vector[2] = pict->transform->matrix[2][0]; + } + else { + unit.vector[0] = xFixed1; + unit.vector[1] = 0; + unit.vector[2] = 0; + } + + dx = pGradient->linear.p2.x - pGradient->linear.p1.x; + dy = pGradient->linear.p2.y - pGradient->linear.p1.y; + l = dx * dx + dy * dy; + if (l != 0) { + a = (dx << 32) / l; + b = (dy << 32) / l; + off = + (-a * pGradient->linear.p1.x - + b * pGradient->linear.p1.y) >> 16; + } + if (l == 0 || (unit.vector[2] == 0 && v.vector[2] == xFixed1)) { + xFixed_48_16 inc, t; + + /* affine transformation only */ + if (l == 0) { + t = 0; + inc = 0; + } + else { + t = ((a * v.vector[0] + b * v.vector[1]) >> 16) + off; + inc = (a * unit.vector[0] + b * unit.vector[1]) >> 16; + } + while (buffer < end) { + *buffer++ = gradientPixel(pGradient, t, pict->repeatType); + t += inc; + } + } + else { + /* projective transformation */ + while (buffer < end) { + xFixed_48_16 t; + + if (v.vector[2] == 0) { + t = 0; + } + else { + xFixed_48_16 x, y; + + x = ((xFixed_48_16) v.vector[0] << 16) / v.vector[2]; + y = ((xFixed_48_16) v.vector[1] << 16) / v.vector[2]; + t = ((a * x + b * y) >> 16) + off; + } + *buffer++ = gradientPixel(pGradient, t, pict->repeatType); + v.vector[0] += unit.vector[0]; + v.vector[1] += unit.vector[1]; + v.vector[2] += unit.vector[2]; + } + } + } + else { + /* radial or conical */ + Bool affine = TRUE; + + double cx = 1.; + + double cy = 0.; + + double cz = 0.; + + double rx = x; + + double ry = y; + + double rz = 1.; + + if (pict->transform) { + PictVector v; + + /* reference point is the center of the pixel */ + v.vector[0] = IntToxFixed(x) + xFixed1 / 2; + v.vector[1] = IntToxFixed(y) + xFixed1 / 2; + v.vector[2] = xFixed1; + if (!PictureTransformPoint3d(pict->transform, &v)) + return; + + cx = pict->transform->matrix[0][0] / 65536.; + cy = pict->transform->matrix[1][0] / 65536.; + cz = pict->transform->matrix[2][0] / 65536.; + rx = v.vector[0] / 65536.; + ry = v.vector[1] / 65536.; + rz = v.vector[2] / 65536.; + affine = pict->transform->matrix[2][0] == 0 && + v.vector[2] == xFixed1; + } + + if (pGradient->type == SourcePictTypeRadial) { + if (affine) { + rx -= pGradient->radial.fx; + ry -= pGradient->radial.fy; + + while (buffer < end) { + double b = + 2 * (rx * pGradient->radial.dx + + ry * pGradient->radial.dy); + double c = -(rx * rx + ry * ry); + + double det = (b * b) - (4 * pGradient->radial.a * c); + + double s = (-b + sqrt(det)) / (2. * pGradient->radial.a); + + *buffer = gradientPixel(pGradient, + (xFixed_48_16) ((s * + pGradient->radial. + m + + pGradient->radial. + b) * 65536), + pict->repeatType); + ++buffer; + rx += cx; + ry += cy; + } + } + else { + while (buffer < end) { + double x, y; + + double b, c, det, s; + + if (rz != 0) { + x = rx / rz; + y = ry / rz; + } + else { + x = y = 0.; + } + x -= pGradient->radial.fx; + y -= pGradient->radial.fy; + b = 2 * (x * pGradient->radial.dx + + y * pGradient->radial.dy); + c = -(x * x + y * y); + det = (b * b) - (4 * pGradient->radial.a * c); + s = (-b + sqrt(det)) / (2. * pGradient->radial.a); + *buffer = gradientPixel(pGradient, + (xFixed_48_16) ((s * + pGradient->radial. + m + + pGradient->radial. + b) * 65536), + pict->repeatType); + ++buffer; + rx += cx; + ry += cy; + rz += cz; + } + } + } + else { /* SourcePictTypeConical */ + + double a = pGradient->conical.angle / (180. * 65536); + + if (affine) { + rx -= pGradient->conical.center.x / 65536.; + ry -= pGradient->conical.center.y / 65536.; + + while (buffer < end) { + double angle = atan2(ry, rx) + a; + + *buffer = + gradientPixel(pGradient, + (xFixed_48_16) (angle * + (65536. / (2 * M_PI))), + pict->repeatType); + ++buffer; + rx += cx; + ry += cy; + } + } + else { + + while (buffer < end) { + double x, y, angle; + + if (rz != 0) { + x = rx / rz; + y = ry / rz; + } + else { + x = y = 0.; + } + x -= pGradient->conical.center.x / 65536.; + y -= pGradient->conical.center.y / 65536.; + angle = atan2(y, x) + a; + *buffer = + gradientPixel(pGradient, + (xFixed_48_16) (angle * + (65536. / (2 * M_PI))), + pict->repeatType); + ++buffer; + rx += cx; + ry += cy; + rz += cz; + } + } + } + } +} + +static void +fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32 *buffer) +{ + FbBits *bits; + + FbStride stride; + + int bpp; + + int xoff, yoff, dx, dy; + + fetchPixelProc fetch; + + PictVector v; + + PictVector unit; + + int i; + + BoxRec box; + + miIndexedPtr indexed = (miIndexedPtr) pict->pFormat->index.devPrivate; + + Bool affine = TRUE; + + fetch = fetchPixelProcForPicture(pict); + + fbGetDrawable(pict->pDrawable, bits, stride, bpp, xoff, yoff); + x += xoff; + y += yoff; + + dx = pict->pDrawable->x; + dy = pict->pDrawable->y; + + /* reference point is the center of the pixel */ + v.vector[0] = IntToxFixed(x - dx) + xFixed1 / 2; + v.vector[1] = IntToxFixed(y - dy) + xFixed1 / 2; + v.vector[2] = xFixed1; + + /* when using convolution filters one might get here without a transform */ + if (pict->transform) { + if (!PictureTransformPoint3d(pict->transform, &v)) + return; + unit.vector[0] = pict->transform->matrix[0][0]; + unit.vector[1] = pict->transform->matrix[1][0]; + unit.vector[2] = pict->transform->matrix[2][0]; + affine = v.vector[2] == xFixed1 && unit.vector[2] == 0; + } + else { + unit.vector[0] = xFixed1; + unit.vector[1] = 0; + unit.vector[2] = 0; + } + + if (pict->filter == PictFilterNearest) { + if (pict->repeatType == RepeatNormal) { + if (REGION_NUM_RECTS(pict->pCompositeClip) == 1) { + for (i = 0; i < width; ++i) { + if (!v.vector[2]) { + buffer[i] = 0; + } + else { + if (!affine) { + y = MOD(DIV(v.vector[1], v.vector[2]), + pict->pDrawable->height); + x = MOD(DIV(v.vector[0], v.vector[2]), + pict->pDrawable->width); + } + else { + y = MOD(v.vector[1] >> 16, pict->pDrawable->height); + x = MOD(v.vector[0] >> 16, pict->pDrawable->width); + } + buffer[i] = + fetch(bits + (y + dy) * stride, x + dx, indexed); + } + v.vector[0] += unit.vector[0]; + v.vector[1] += unit.vector[1]; + v.vector[2] += unit.vector[2]; + } + } + else { + for (i = 0; i < width; ++i) { + if (!v.vector[2]) { + buffer[i] = 0; + } + else { + if (!affine) { + y = MOD(DIV(v.vector[1], v.vector[2]), + pict->pDrawable->height); + x = MOD(DIV(v.vector[0], v.vector[2]), + pict->pDrawable->width); + } + else { + y = MOD(v.vector[1] >> 16, pict->pDrawable->height); + x = MOD(v.vector[0] >> 16, pict->pDrawable->width); + } + if (POINT_IN_REGION(pict->pCompositeClip, x + dx, y + dy, &box)) + buffer[i] = + fetch(bits + (y + dy) * stride, x + dx, + indexed); + else + buffer[i] = 0; + } + v.vector[0] += unit.vector[0]; + v.vector[1] += unit.vector[1]; + v.vector[2] += unit.vector[2]; + } + } + } + else { + if (REGION_NUM_RECTS(pict->pCompositeClip) == 1) { + box = pict->pCompositeClip->extents; + for (i = 0; i < width; ++i) { + if (!v.vector[2]) { + buffer[i] = 0; + } + else { + if (!affine) { + y = DIV(v.vector[1], v.vector[2]); + x = DIV(v.vector[0], v.vector[2]); + } + else { + y = v.vector[1] >> 16; + x = v.vector[0] >> 16; + } + buffer[i] = + ((x < box.x1 - dx) | (x >= box.x2 - dx) | (y < + box.y1 - + dy) | (y + >= + box. + y2 + - + dy)) + ? 0 : fetch(bits + (y + dy) * stride, x + dx, + indexed); + } + v.vector[0] += unit.vector[0]; + v.vector[1] += unit.vector[1]; + v.vector[2] += unit.vector[2]; + } + } + else { + for (i = 0; i < width; ++i) { + if (!v.vector[2]) { + buffer[i] = 0; + } + else { + if (!affine) { + y = DIV(v.vector[1], v.vector[2]); + x = DIV(v.vector[0], v.vector[2]); + } + else { + y = v.vector[1] >> 16; + x = v.vector[0] >> 16; + } + if (POINT_IN_REGION(pict->pCompositeClip, x + dx, y + dy, &box)) + buffer[i] = + fetch(bits + (y + dy) * stride, x + dx, + indexed); + else + buffer[i] = 0; + } + v.vector[0] += unit.vector[0]; + v.vector[1] += unit.vector[1]; + v.vector[2] += unit.vector[2]; + } + } + } + } + else if (pict->filter == PictFilterBilinear) { + /* adjust vector for maximum contribution at 0.5, 0.5 of each texel. */ + v.vector[0] -= v.vector[2] / 2; + v.vector[1] -= v.vector[2] / 2; + unit.vector[0] -= unit.vector[2] / 2; + unit.vector[1] -= unit.vector[2] / 2; + + if (pict->repeatType == RepeatNormal) { + if (REGION_NUM_RECTS(pict->pCompositeClip) == 1) { + for (i = 0; i < width; ++i) { + if (!v.vector[2]) { + buffer[i] = 0; + } + else { + int x1, x2, y1, y2, distx, idistx, disty, idisty; + + FbBits *b; + + CARD32 tl, tr, bl, br, r; + + CARD32 ft, fb; + + if (!affine) { + xFixed_48_16 div; + + div = + ((xFixed_48_16) v.vector[0] << 16) / + v.vector[2]; + x1 = div >> 16; + distx = ((xFixed) div >> 8) & 0xff; + div = + ((xFixed_48_16) v.vector[1] << 16) / + v.vector[2]; + y1 = div >> 16; + disty = ((xFixed) div >> 8) & 0xff; + } + else { + x1 = v.vector[0] >> 16; + distx = (v.vector[0] >> 8) & 0xff; + y1 = v.vector[1] >> 16; + disty = (v.vector[1] >> 8) & 0xff; + } + x2 = x1 + 1; + y2 = y1 + 1; + + idistx = 256 - distx; + idisty = 256 - disty; + + x1 = MOD(x1, pict->pDrawable->width); + x2 = MOD(x2, pict->pDrawable->width); + y1 = MOD(y1, pict->pDrawable->height); + y2 = MOD(y2, pict->pDrawable->height); + + b = bits + (y1 + dy) * stride; + + tl = fetch(b, x1 + dx, indexed); + tr = fetch(b, x2 + dx, indexed); + b = bits + (y2 + dy) * stride; + bl = fetch(b, x1 + dx, indexed); + br = fetch(b, x2 + dx, indexed); + + ft = FbGet8(tl, 0) * idistx + FbGet8(tr, 0) * distx; + fb = FbGet8(bl, 0) * idistx + FbGet8(br, 0) * distx; + r = (((ft * idisty + fb * disty) >> 16) & 0xff); + ft = FbGet8(tl, 8) * idistx + FbGet8(tr, 8) * distx; + fb = FbGet8(bl, 8) * idistx + FbGet8(br, 8) * distx; + r |= (((ft * idisty + fb * disty) >> 8) & 0xff00); + ft = FbGet8(tl, 16) * idistx + FbGet8(tr, 16) * distx; + fb = FbGet8(bl, 16) * idistx + FbGet8(br, 16) * distx; + r |= (((ft * idisty + fb * disty)) & 0xff0000); + ft = FbGet8(tl, 24) * idistx + FbGet8(tr, 24) * distx; + fb = FbGet8(bl, 24) * idistx + FbGet8(br, 24) * distx; + r |= (((ft * idisty + fb * disty) << 8) & 0xff000000); + buffer[i] = r; + } + v.vector[0] += unit.vector[0]; + v.vector[1] += unit.vector[1]; + v.vector[2] += unit.vector[2]; + } + } + else { + for (i = 0; i < width; ++i) { + if (!v.vector[2]) { + buffer[i] = 0; + } + else { + int x1, x2, y1, y2, distx, idistx, disty, idisty; + + FbBits *b; + + CARD32 tl, tr, bl, br, r; + + CARD32 ft, fb; + + if (!affine) { + xFixed_48_16 div; + + div = + ((xFixed_48_16) v.vector[0] << 16) / + v.vector[2]; + x1 = div >> 16; + distx = ((xFixed) div >> 8) & 0xff; + div = + ((xFixed_48_16) v.vector[1] << 16) / + v.vector[2]; + y1 = div >> 16; + disty = ((xFixed) div >> 8) & 0xff; + } + else { + x1 = v.vector[0] >> 16; + distx = (v.vector[0] >> 8) & 0xff; + y1 = v.vector[1] >> 16; + disty = (v.vector[1] >> 8) & 0xff; + } + x2 = x1 + 1; + y2 = y1 + 1; + + idistx = 256 - distx; + idisty = 256 - disty; + + x1 = MOD(x1, pict->pDrawable->width); + x2 = MOD(x2, pict->pDrawable->width); + y1 = MOD(y1, pict->pDrawable->height); + y2 = MOD(y2, pict->pDrawable->height); + + b = bits + (y1 + dy) * stride; + + tl = POINT_IN_REGION(pict->pCompositeClip, x1 + dx, + y1 + dy, &box) + ? fetch(b, x1 + dx, indexed) : 0; + tr = POINT_IN_REGION(pict->pCompositeClip, x2 + dx, + y1 + dy, &box) + ? fetch(b, x2 + dx, indexed) : 0; + b = bits + (y2 + dy) * stride; + bl = POINT_IN_REGION(pict->pCompositeClip, x1 + dx, + y2 + dy, &box) + ? fetch(b, x1 + dx, indexed) : 0; + br = POINT_IN_REGION(pict->pCompositeClip, x2 + dx, + y2 + dy, &box) + ? fetch(b, x2 + dx, indexed) : 0; + + ft = FbGet8(tl, 0) * idistx + FbGet8(tr, 0) * distx; + fb = FbGet8(bl, 0) * idistx + FbGet8(br, 0) * distx; + r = (((ft * idisty + fb * disty) >> 16) & 0xff); + ft = FbGet8(tl, 8) * idistx + FbGet8(tr, 8) * distx; + fb = FbGet8(bl, 8) * idistx + FbGet8(br, 8) * distx; + r |= (((ft * idisty + fb * disty) >> 8) & 0xff00); + ft = FbGet8(tl, 16) * idistx + FbGet8(tr, 16) * distx; + fb = FbGet8(bl, 16) * idistx + FbGet8(br, 16) * distx; + r |= (((ft * idisty + fb * disty)) & 0xff0000); + ft = FbGet8(tl, 24) * idistx + FbGet8(tr, 24) * distx; + fb = FbGet8(bl, 24) * idistx + FbGet8(br, 24) * distx; + r |= (((ft * idisty + fb * disty) << 8) & 0xff000000); + buffer[i] = r; + } + v.vector[0] += unit.vector[0]; + v.vector[1] += unit.vector[1]; + v.vector[2] += unit.vector[2]; + } + } + } + else { + if (REGION_NUM_RECTS(pict->pCompositeClip) == 1) { + box = pict->pCompositeClip->extents; + for (i = 0; i < width; ++i) { + if (!v.vector[2]) { + buffer[i] = 0; + } + else { + int x1, x2, y1, y2, distx, idistx, disty, idisty, x_off; + + FbBits *b; + + CARD32 tl, tr, bl, br, r; + + Bool x1_out, x2_out, y1_out, y2_out; + + CARD32 ft, fb; + + if (!affine) { + xFixed_48_16 div; + + div = + ((xFixed_48_16) v.vector[0] << 16) / + v.vector[2]; + x1 = div >> 16; + distx = ((xFixed) div >> 8) & 0xff; + div = + ((xFixed_48_16) v.vector[1] << 16) / + v.vector[2]; + y1 = div >> 16; + disty = ((xFixed) div >> 8) & 0xff; + } + else { + x1 = v.vector[0] >> 16; + distx = (v.vector[0] >> 8) & 0xff; + y1 = v.vector[1] >> 16; + disty = (v.vector[1] >> 8) & 0xff; + } + x2 = x1 + 1; + y2 = y1 + 1; + + idistx = 256 - distx; + idisty = 256 - disty; + + b = bits + (y1 + dy) * stride; + x_off = x1 + dx; + + x1_out = (x1 < box.x1 - dx) | (x1 >= box.x2 - dx); + x2_out = (x2 < box.x1 - dx) | (x2 >= box.x2 - dx); + y1_out = (y1 < box.y1 - dy) | (y1 >= box.y2 - dy); + y2_out = (y2 < box.y1 - dy) | (y2 >= box.y2 - dy); + + tl = x1_out | y1_out ? 0 : fetch(b, x_off, indexed); + tr = x2_out | y1_out ? 0 : fetch(b, x_off + 1, indexed); + b += stride; + bl = x1_out | y2_out ? 0 : fetch(b, x_off, indexed); + br = x2_out | y2_out ? 0 : fetch(b, x_off + 1, indexed); + + ft = FbGet8(tl, 0) * idistx + FbGet8(tr, 0) * distx; + fb = FbGet8(bl, 0) * idistx + FbGet8(br, 0) * distx; + r = (((ft * idisty + fb * disty) >> 16) & 0xff); + ft = FbGet8(tl, 8) * idistx + FbGet8(tr, 8) * distx; + fb = FbGet8(bl, 8) * idistx + FbGet8(br, 8) * distx; + r |= (((ft * idisty + fb * disty) >> 8) & 0xff00); + ft = FbGet8(tl, 16) * idistx + FbGet8(tr, 16) * distx; + fb = FbGet8(bl, 16) * idistx + FbGet8(br, 16) * distx; + r |= (((ft * idisty + fb * disty)) & 0xff0000); + ft = FbGet8(tl, 24) * idistx + FbGet8(tr, 24) * distx; + fb = FbGet8(bl, 24) * idistx + FbGet8(br, 24) * distx; + r |= (((ft * idisty + fb * disty) << 8) & 0xff000000); + buffer[i] = r; + } + v.vector[0] += unit.vector[0]; + v.vector[1] += unit.vector[1]; + v.vector[2] += unit.vector[2]; + } + } + else { + for (i = 0; i < width; ++i) { + if (!v.vector[2]) { + buffer[i] = 0; + } + else { + int x1, x2, y1, y2, distx, idistx, disty, idisty, x_off; + + FbBits *b; + + CARD32 tl, tr, bl, br, r; + + CARD32 ft, fb; + + if (!affine) { + xFixed_48_16 div; + + div = + ((xFixed_48_16) v.vector[0] << 16) / + v.vector[2]; + x1 = div >> 16; + distx = ((xFixed) div >> 8) & 0xff; + div = + ((xFixed_48_16) v.vector[1] << 16) / + v.vector[2]; + y1 = div >> 16; + disty = ((xFixed) div >> 8) & 0xff; + } + else { + x1 = v.vector[0] >> 16; + distx = (v.vector[0] >> 8) & 0xff; + y1 = v.vector[1] >> 16; + disty = (v.vector[1] >> 8) & 0xff; + } + x2 = x1 + 1; + y2 = y1 + 1; + + idistx = 256 - distx; + idisty = 256 - disty; + + b = bits + (y1 + dy) * stride; + x_off = x1 + dx; + + tl = POINT_IN_REGION(pict->pCompositeClip, x1 + dx, + y1 + dy, &box) + ? fetch(b, x_off, indexed) : 0; + tr = POINT_IN_REGION(pict->pCompositeClip, x2 + dx, + y1 + dy, &box) + ? fetch(b, x_off + 1, indexed) : 0; + b += stride; + bl = POINT_IN_REGION(pict->pCompositeClip, x1 + dx, + y2 + dy, &box) + ? fetch(b, x_off, indexed) : 0; + br = POINT_IN_REGION(pict->pCompositeClip, x2 + dx, + y2 + dy, &box) + ? fetch(b, x_off + 1, indexed) : 0; + + ft = FbGet8(tl, 0) * idistx + FbGet8(tr, 0) * distx; + fb = FbGet8(bl, 0) * idistx + FbGet8(br, 0) * distx; + r = (((ft * idisty + fb * disty) >> 16) & 0xff); + ft = FbGet8(tl, 8) * idistx + FbGet8(tr, 8) * distx; + fb = FbGet8(bl, 8) * idistx + FbGet8(br, 8) * distx; + r |= (((ft * idisty + fb * disty) >> 8) & 0xff00); + ft = FbGet8(tl, 16) * idistx + FbGet8(tr, 16) * distx; + fb = FbGet8(bl, 16) * idistx + FbGet8(br, 16) * distx; + r |= (((ft * idisty + fb * disty)) & 0xff0000); + ft = FbGet8(tl, 24) * idistx + FbGet8(tr, 24) * distx; + fb = FbGet8(bl, 24) * idistx + FbGet8(br, 24) * distx; + r |= (((ft * idisty + fb * disty) << 8) & 0xff000000); + buffer[i] = r; + } + v.vector[0] += unit.vector[0]; + v.vector[1] += unit.vector[1]; + v.vector[2] += unit.vector[2]; + } + } + } + } + else if (pict->filter == PictFilterConvolution) { + xFixed *params = pict->filter_params; + + INT32 cwidth = xFixedToInt(params[0]); + + INT32 cheight = xFixedToInt(params[1]); + + int xoff = (params[0] - xFixed1) >> 1; + + int yoff = (params[1] - xFixed1) >> 1; + + params += 2; + for (i = 0; i < width; ++i) { + if (!v.vector[2]) { + buffer[i] = 0; + } + else { + int x1, x2, y1, y2, x, y; + + INT32 srtot, sgtot, sbtot, satot; + + xFixed *p = params; + + if (!affine) { + xFixed_48_16 tmp; + + tmp = + ((xFixed_48_16) v.vector[0] << 16) / v.vector[2] - xoff; + x1 = xFixedToInt(tmp); + tmp = + ((xFixed_48_16) v.vector[1] << 16) / v.vector[2] - yoff; + y1 = xFixedToInt(tmp); + } + else { + x1 = xFixedToInt(v.vector[0] - xoff); + y1 = xFixedToInt(v.vector[1] - yoff); + } + x2 = x1 + cwidth; + y2 = y1 + cheight; + + srtot = sgtot = sbtot = satot = 0; + + for (y = y1; y < y2; y++) { + int ty = + (pict->repeatType == RepeatNormal) ? MOD(y, + pict-> + pDrawable-> + height) : y; + for (x = x1; x < x2; x++) { + if (*p) { + int tx = + (pict->repeatType == RepeatNormal) ? MOD(x, + pict-> + pDrawable-> + width) + : x; + if (POINT_IN_REGION(pict->pCompositeClip, tx + dx, ty + dy, + &box)) { + FbBits *b = bits + (ty + dy) * stride; + + CARD32 c = fetch(b, tx + dx, indexed); + + srtot += Red(c) * *p; + sgtot += Green(c) * *p; + sbtot += Blue(c) * *p; + satot += Alpha(c) * *p; + } + } + p++; + } + } + + satot >>= 16; + srtot >>= 16; + sgtot >>= 16; + sbtot >>= 16; + + if (satot < 0) + satot = 0; + else if (satot > 0xff) + satot = 0xff; + if (srtot < 0) + srtot = 0; + else if (srtot > 0xff) + srtot = 0xff; + if (sgtot < 0) + sgtot = 0; + else if (sgtot > 0xff) + sgtot = 0xff; + if (sbtot < 0) + sbtot = 0; + else if (sbtot > 0xff) + sbtot = 0xff; + + buffer[i] = ((satot << 24) | + (srtot << 16) | (sgtot << 8) | (sbtot)); + } + v.vector[0] += unit.vector[0]; + v.vector[1] += unit.vector[1]; + v.vector[2] += unit.vector[2]; + } + } +} + +static void +fbFetchExternalAlpha(PicturePtr pict, int x, int y, int width, CARD32 *buffer) +{ + int i; + + CARD32 _alpha_buffer[SCANLINE_BUFFER_LENGTH]; + + CARD32 *alpha_buffer = _alpha_buffer; + + if (!pict->alphaMap) { + fbFetchTransformed(pict, x, y, width, buffer); + return; + } + if (width > SCANLINE_BUFFER_LENGTH) + alpha_buffer = malloc(width * sizeof(CARD32)); + + fbFetchTransformed(pict, x, y, width, buffer); + fbFetchTransformed(pict->alphaMap, x - pict->alphaOrigin.x, + y - pict->alphaOrigin.y, width, alpha_buffer); + for (i = 0; i < width; ++i) { + int a = alpha_buffer[i] >> 24; + + buffer[i] = (a << 24) + | (div_255(Red(buffer[i]) * a) << 16) + | (div_255(Green(buffer[i]) * a) << 8) + | (div_255(Blue(buffer[i]) * a)); + } + + if (alpha_buffer != _alpha_buffer) + free(alpha_buffer); +} + +static void +fbStore(PicturePtr pict, int x, int y, int width, CARD32 *buffer) +{ + FbBits *bits; + + FbStride stride; + + int bpp; + + int xoff, yoff; + + storeProc store = storeProcForPicture(pict); + + miIndexedPtr indexed = (miIndexedPtr) pict->pFormat->index.devPrivate; + + fbGetDrawable(pict->pDrawable, bits, stride, bpp, xoff, yoff); + x += xoff; + y += yoff; + + bits += y * stride; + store(bits, buffer, x, width, indexed); +} + +static void +fbStoreExternalAlpha(PicturePtr pict, int x, int y, int width, CARD32 *buffer) +{ + FbBits *bits, *alpha_bits; + + FbStride stride, astride; + + int bpp, abpp; + + int xoff, yoff; + + int ax, ay; + + storeProc store; + + storeProc astore; + + miIndexedPtr indexed = (miIndexedPtr) pict->pFormat->index.devPrivate; + + miIndexedPtr aindexed; + + if (!pict->alphaMap) { + fbStore(pict, x, y, width, buffer); + return; + } + + store = storeProcForPicture(pict); + astore = storeProcForPicture(pict->alphaMap); + aindexed = (miIndexedPtr) pict->alphaMap->pFormat->index.devPrivate; + + ax = x; + ay = y; + + fbGetDrawable(pict->pDrawable, bits, stride, bpp, xoff, yoff); + x += xoff; + y += yoff; + fbGetDrawable(pict->alphaMap->pDrawable, alpha_bits, astride, abpp, xoff, + yoff); + ax += xoff; + ay += yoff; + + bits += y * stride; + alpha_bits += (ay - pict->alphaOrigin.y) * astride; + + store(bits, buffer, x, width, indexed); + astore(alpha_bits, buffer, ax - pict->alphaOrigin.x, width, aindexed); +} + +typedef void (*scanStoreProc) (PicturePtr, int, int, int, CARD32 *); + +typedef void (*scanFetchProc) (PicturePtr, int, int, int, CARD32 *); + +static void +fbCompositeRect(const FbComposeData * data, CARD32 *scanline_buffer) +{ + CARD32 *src_buffer = scanline_buffer; + + CARD32 *dest_buffer = src_buffer + data->width; + + int i; + + scanStoreProc store; + + scanFetchProc fetchSrc = NULL, fetchMask = NULL, fetchDest = NULL; + + if (data->op == PictOpClear) + fetchSrc = NULL; + else if (!data->src->pDrawable) { + if (data->src->pSourcePict) + fetchSrc = fbFetchSourcePict; + } + else if (data->src->alphaMap) + fetchSrc = fbFetchExternalAlpha; + else if (data->src->repeatType == RepeatNormal && + data->src->pDrawable->width == 1 && + data->src->pDrawable->height == 1) + fetchSrc = fbFetchSolid; + else if (!data->src->transform && + data->src->filter != PictFilterConvolution) + fetchSrc = fbFetch; + else + fetchSrc = fbFetchTransformed; + + if (data->mask && data->op != PictOpClear) { + if (!data->mask->pDrawable) { + if (data->mask->pSourcePict) + fetchMask = fbFetchSourcePict; + } + else if (data->mask->alphaMap) + fetchMask = fbFetchExternalAlpha; + else if (data->mask->repeatType == RepeatNormal + && data->mask->pDrawable->width == 1 && + data->mask->pDrawable->height == 1) + fetchMask = fbFetchSolid; + else if (!data->mask->transform && + data->mask->filter != PictFilterConvolution) + fetchMask = fbFetch; + else + fetchMask = fbFetchTransformed; + } + else { + fetchMask = NULL; + } + + if (data->dest->alphaMap) { + fetchDest = fbFetchExternalAlpha; + store = fbStoreExternalAlpha; + } + else { + fetchDest = fbFetch; + store = fbStore; + } + if (data->op == PictOpClear || data->op == PictOpSrc) + fetchDest = NULL; + + if (fetchSrc && fetchMask && data->mask && data->mask->componentAlpha && + PICT_FORMAT_RGB(data->mask->format)) { + CARD32 *mask_buffer = dest_buffer + data->width; + + CombineFuncC compose = composeFunctions.combineC[data->op]; + + if (!compose) + return; + + for (i = 0; i < data->height; ++i) { + /* fill first half of scanline with source */ + fetchSrc(data->src, data->xSrc, data->ySrc + i, data->width, + src_buffer); + fetchMask(data->mask, data->xMask, data->yMask + i, data->width, + mask_buffer); + + /* fill dest into second half of scanline */ + if (fetchDest) + fetchDest(data->dest, data->xDest, data->yDest + i, data->width, + dest_buffer); + + /* blend */ + compose(dest_buffer, src_buffer, mask_buffer, data->width); + + /* write back */ + store(data->dest, data->xDest, data->yDest + i, data->width, + dest_buffer); + } + } + else { + + CombineFuncU compose = composeFunctions.combineU[data->op]; + + if (!compose) + return; + + if (fetchSrc == fbFetchSolid && + (!fetchMask || fetchMask == fbFetchSolid)) { + fetchSrc(data->src, data->xSrc, data->ySrc, data->width, + src_buffer); + if (fetchMask) { + fetchMask(data->mask, data->xMask, data->yMask, data->width, + dest_buffer); + composeFunctions.combineMaskU(src_buffer, dest_buffer, + data->width); + } + fetchSrc = NULL; + fetchMask = NULL; + } + + for (i = 0; i < data->height; ++i) { + /* fill first half of scanline with source */ + if (fetchSrc) { + fetchSrc(data->src, data->xSrc, data->ySrc + i, data->width, + src_buffer); + + /* add in mask */ + if (fetchMask) { + fetchMask(data->mask, data->xMask, data->yMask + i, + data->width, dest_buffer); + composeFunctions.combineMaskU(src_buffer, dest_buffer, + data->width); + } + } + + /* fill dest into second half of scanline */ + if (fetchDest) + fetchDest(data->dest, data->xDest, data->yDest + i, data->width, + dest_buffer); + + /* blend */ + compose(dest_buffer, src_buffer, data->width); + + /* write back */ + store(data->dest, data->xDest, data->yDest + i, data->width, + dest_buffer); + } + } +} + +void +fbCompositeGeneral(CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, INT16 yDst, CARD16 width, CARD16 height) +{ + RegionRec region; + + int n; + + BoxPtr pbox; + + Bool srcRepeat = FALSE; + + Bool maskRepeat = FALSE; + + int w, h; + + CARD32 _scanline_buffer[SCANLINE_BUFFER_LENGTH * 3]; + + CARD32 *scanline_buffer = _scanline_buffer; + + FbComposeData compose_data; + + if (pSrc->pDrawable) + srcRepeat = pSrc->repeatType == RepeatNormal && !pSrc->transform + && (pSrc->pDrawable->width != 1 || pSrc->pDrawable->height != 1); + + if (pMask && pMask->pDrawable) + maskRepeat = pMask->repeatType == RepeatNormal && !pMask->transform + && (pMask->pDrawable->width != 1 || pMask->pDrawable->height != 1); + + if (op == PictOpOver && !pMask && !pSrc->transform && + !PICT_FORMAT_A(pSrc->format) && !pSrc->alphaMap) + op = PictOpSrc; + + if (!miComputeCompositeRegion(®ion, + pSrc, + pMask, + pDst, + xSrc, + ySrc, + xMask, yMask, xDst, yDst, width, height)) + return; + + compose_data.op = op; + compose_data.src = pSrc; + compose_data.mask = pMask; + compose_data.dest = pDst; + if (width > SCANLINE_BUFFER_LENGTH) + scanline_buffer = malloc(width * 3 * sizeof(CARD32)); + + n = REGION_NUM_RECTS(®ion); + pbox = REGION_RECTS(®ion); + while (n--) { + h = pbox->y2 - pbox->y1; + compose_data.ySrc = pbox->y1 - yDst + ySrc; + compose_data.yMask = pbox->y1 - yDst + yMask; + compose_data.yDest = pbox->y1; + while (h) { + compose_data.height = h; + w = pbox->x2 - pbox->x1; + compose_data.xSrc = pbox->x1 - xDst + xSrc; + compose_data.xMask = pbox->x1 - xDst + xMask; + compose_data.xDest = pbox->x1; + if (maskRepeat) { + compose_data.yMask = + mod(compose_data.yMask, pMask->pDrawable->height); + if (compose_data.height > + pMask->pDrawable->height - compose_data.yMask) + compose_data.height = + pMask->pDrawable->height - compose_data.yMask; + } + if (srcRepeat) { + compose_data.ySrc = + mod(compose_data.ySrc, pSrc->pDrawable->height); + if (compose_data.height > + pSrc->pDrawable->height - compose_data.ySrc) + compose_data.height = + pSrc->pDrawable->height - compose_data.ySrc; + } + while (w) { + compose_data.width = w; + if (maskRepeat) { + compose_data.xMask = + mod(compose_data.xMask, pMask->pDrawable->width); + if (compose_data.width > + pMask->pDrawable->width - compose_data.xMask) + compose_data.width = + pMask->pDrawable->width - compose_data.xMask; + } + if (srcRepeat) { + compose_data.xSrc = + mod(compose_data.xSrc, pSrc->pDrawable->width); + if (compose_data.width > + pSrc->pDrawable->width - compose_data.xSrc) + compose_data.width = + pSrc->pDrawable->width - compose_data.xSrc; + } + fbCompositeRect(&compose_data, scanline_buffer); + w -= compose_data.width; + compose_data.xSrc += compose_data.width; + compose_data.xMask += compose_data.width; + compose_data.xDest += compose_data.width; + } + h -= compose_data.height; + compose_data.ySrc += compose_data.height; + compose_data.yMask += compose_data.height; + compose_data.yDest += compose_data.height; + } + pbox++; + } + REGION_UNINIT(®ion); + + if (scanline_buffer != _scanline_buffer) + free(scanline_buffer); +} + diff --git a/fb/fbcopy.c b/fb/fbcopy.c new file mode 100644 index 0000000..b897900 --- /dev/null +++ b/fb/fbcopy.c @@ -0,0 +1,584 @@ +/* + * + * Copyright © 1998 Keith Packard + * + * 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, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include + +#include "fb.h" + +void +fbCopyNtoN(DrawablePtr pSrcDrawable, + DrawablePtr pDstDrawable, + GCPtr pGC, + BoxPtr pbox, + int nbox, + int dx, + int dy, Bool reverse, Bool upsidedown, Pixel bitplane, void *closure) +{ + CARD8 alu = pGC ? pGC->alu : GXcopy; + + FbBits pm = pGC ? fbGetGCPrivate(pGC)->pm : FB_ALLONES; + + FbBits *src; + + FbStride srcStride; + + int srcBpp; + + int srcXoff, srcYoff; + + FbBits *dst; + + FbStride dstStride; + + int dstBpp; + + int dstXoff, dstYoff; + + fbGetDrawable(pSrcDrawable, src, srcStride, srcBpp, srcXoff, srcYoff); + fbGetDrawable(pDstDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); + + while (nbox--) { + fbBlt(src + (pbox->y1 + dy + srcYoff) * srcStride, + srcStride, + (pbox->x1 + dx + srcXoff) * srcBpp, + dst + (pbox->y1 + dstYoff) * dstStride, + dstStride, + (pbox->x1 + dstXoff) * dstBpp, + (pbox->x2 - pbox->x1) * dstBpp, + (pbox->y2 - pbox->y1), alu, pm, dstBpp, reverse, upsidedown); + pbox++; + } +} + +void +fbCopy1toN(DrawablePtr pSrcDrawable, + DrawablePtr pDstDrawable, + GCPtr pGC, + BoxPtr pbox, + int nbox, + int dx, + int dy, Bool reverse, Bool upsidedown, Pixel bitplane, void *closure) +{ + FbGCPrivPtr pPriv = fbGetGCPrivate(pGC); + + FbBits *src; + + FbStride srcStride; + + int srcBpp; + + int srcXoff, srcYoff; + + FbBits *dst; + + FbStride dstStride; + + int dstBpp; + + int dstXoff, dstYoff; + + fbGetDrawable(pSrcDrawable, src, srcStride, srcBpp, srcXoff, srcYoff); + fbGetDrawable(pDstDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); + + while (nbox--) { + if (dstBpp == 1) { + fbBlt(src + (pbox->y1 + dy + srcYoff) * srcStride, + srcStride, + (pbox->x1 + dx + srcXoff) * srcBpp, + dst + (pbox->y1 + dstYoff) * dstStride, + dstStride, + (pbox->x1 + dstXoff) * dstBpp, + (pbox->x2 - pbox->x1) * dstBpp, + (pbox->y2 - pbox->y1), + FbOpaqueStipple1Rop(pGC->alu, + pGC->fgPixel, pGC->bgPixel), + pPriv->pm, dstBpp, reverse, upsidedown); + } + else { + fbBltOne((FbStip *) (src + (pbox->y1 + dy + srcYoff) * srcStride), + srcStride * (FB_UNIT / FB_STIP_UNIT), + (pbox->x1 + dx + srcXoff), + dst + (pbox->y1 + dstYoff) * dstStride, + dstStride, + (pbox->x1 + dstXoff) * dstBpp, + dstBpp, + (pbox->x2 - pbox->x1) * dstBpp, + (pbox->y2 - pbox->y1), + pPriv->and, pPriv->xor, pPriv->bgand, pPriv->bgxor); + } + pbox++; + } +} + +void +fbCopyNto1(DrawablePtr pSrcDrawable, + DrawablePtr pDstDrawable, + GCPtr pGC, + BoxPtr pbox, + int nbox, + int dx, + int dy, Bool reverse, Bool upsidedown, Pixel bitplane, void *closure) +{ + FbGCPrivPtr pPriv = fbGetGCPrivate(pGC); + + while (nbox--) { + if (pDstDrawable->bitsPerPixel == 1) { + FbBits *src; + + FbStride srcStride; + + int srcBpp; + + int srcXoff, srcYoff; + + FbStip *dst; + + FbStride dstStride; + + int dstBpp; + + int dstXoff, dstYoff; + + fbGetDrawable(pSrcDrawable, src, srcStride, srcBpp, srcXoff, + srcYoff); + fbGetStipDrawable(pDstDrawable, dst, dstStride, dstBpp, dstXoff, + dstYoff); + fbBltPlane(src + (pbox->y1 + dy + srcYoff) * srcStride, srcStride, + (pbox->x1 + dx + srcXoff) * srcBpp, srcBpp, + dst + (pbox->y1 + dstYoff) * dstStride, dstStride, + (pbox->x1 + dstXoff) * dstBpp, + (pbox->x2 - pbox->x1) * srcBpp, (pbox->y2 - pbox->y1), + (FbStip) pPriv->and, (FbStip) pPriv->xor, + (FbStip) pPriv->bgand, (FbStip) pPriv->bgxor, bitplane); + } + else { + FbBits *src; + + FbStride srcStride; + + int srcBpp; + + int srcXoff, srcYoff; + + FbBits *dst; + + FbStride dstStride; + + int dstBpp; + + int dstXoff, dstYoff; + + FbStip *tmp; + + FbStride tmpStride; + + int width, height; + + width = pbox->x2 - pbox->x1; + height = pbox->y2 - pbox->y1; + + tmpStride = ((width + FB_STIP_MASK) >> FB_STIP_SHIFT); + tmp = malloc(tmpStride * height * sizeof(FbStip)); + if (!tmp) + return; + + fbGetDrawable(pSrcDrawable, src, srcStride, srcBpp, srcXoff, + srcYoff); + fbGetDrawable(pDstDrawable, dst, dstStride, dstBpp, dstXoff, + dstYoff); + + fbBltPlane(src + (pbox->y1 + dy + srcYoff) * srcStride, + srcStride, + (pbox->x1 + dx + srcXoff) * srcBpp, + srcBpp, + tmp, + tmpStride, + 0, + width * srcBpp, + height, + fbAndStip(GXcopy, FB_ALLONES, FB_ALLONES), + fbXorStip(GXcopy, FB_ALLONES, FB_ALLONES), + fbAndStip(GXcopy, 0, FB_ALLONES), + fbXorStip(GXcopy, 0, FB_ALLONES), bitplane); + fbBltOne(tmp, + tmpStride, + 0, + dst + (pbox->y1 + dstYoff) * dstStride, + dstStride, + (pbox->x1 + dstXoff) * dstBpp, + dstBpp, + width * dstBpp, + height, + pPriv->and, pPriv->xor, pPriv->bgand, pPriv->bgxor); + free(tmp); + } + pbox++; + } +} + +void +fbCopyRegion(DrawablePtr pSrcDrawable, + DrawablePtr pDstDrawable, + GCPtr pGC, + RegionPtr pDstRegion, + int dx, int dy, fbCopyProc copyProc, Pixel bitPlane, void *closure) +{ + int careful; + + Bool reverse; + + Bool upsidedown; + + BoxPtr pbox; + + int nbox; + + BoxPtr pboxNew1, pboxNew2, pboxBase, pboxNext, pboxTmp; + + pbox = REGION_RECTS(pDstRegion); + nbox = REGION_NUM_RECTS(pDstRegion); + + /* XXX we have to err on the side of safety when both are windows, + * because we don't know if IncludeInferiors is being used. + */ + careful = ((pSrcDrawable == pDstDrawable) || + ((pSrcDrawable->type == DRAWABLE_WINDOW) && + (pDstDrawable->type == DRAWABLE_WINDOW))); + + pboxNew1 = NULL; + pboxNew2 = NULL; + if (careful && dy < 0) { + upsidedown = TRUE; + + if (nbox > 1) { + /* keep ordering in each band, reverse order of bands */ + pboxNew1 = (BoxPtr) ALLOCATE_LOCAL(sizeof(BoxRec) * nbox); + if (!pboxNew1) + return; + pboxBase = pboxNext = pbox + nbox - 1; + while (pboxBase >= pbox) { + while ((pboxNext >= pbox) && (pboxBase->y1 == pboxNext->y1)) + pboxNext--; + pboxTmp = pboxNext + 1; + while (pboxTmp <= pboxBase) { + *pboxNew1++ = *pboxTmp++; + } + pboxBase = pboxNext; + } + pboxNew1 -= nbox; + pbox = pboxNew1; + } + } + else { + /* walk source top to bottom */ + upsidedown = FALSE; + } + + if (careful && dx < 0) { + /* walk source right to left */ + if (dy <= 0) + reverse = TRUE; + else + reverse = FALSE; + + if (nbox > 1) { + /* reverse order of rects in each band */ + pboxNew2 = (BoxPtr) ALLOCATE_LOCAL(sizeof(BoxRec) * nbox); + if (!pboxNew2) { + if (pboxNew1) + DEALLOCATE_LOCAL(pboxNew1); + return; + } + pboxBase = pboxNext = pbox; + while (pboxBase < pbox + nbox) { + while ((pboxNext < pbox + nbox) && + (pboxNext->y1 == pboxBase->y1)) + pboxNext++; + pboxTmp = pboxNext; + while (pboxTmp != pboxBase) { + *pboxNew2++ = *--pboxTmp; + } + pboxBase = pboxNext; + } + pboxNew2 -= nbox; + pbox = pboxNew2; + } + } + else { + /* walk source left to right */ + reverse = FALSE; + } + + (*copyProc) (pSrcDrawable, + pDstDrawable, + pGC, + pbox, nbox, dx, dy, reverse, upsidedown, bitPlane, closure); + + if (pboxNew1) + DEALLOCATE_LOCAL(pboxNew1); + if (pboxNew2) + DEALLOCATE_LOCAL(pboxNew2); +} + +RegionPtr +fbDoCopy(DrawablePtr pSrcDrawable, + DrawablePtr pDstDrawable, + GCPtr pGC, + int xIn, + int yIn, + int widthSrc, + int heightSrc, + int xOut, int yOut, fbCopyProc copyProc, Pixel bitPlane, void *closure) +{ + RegionPtr prgnSrcClip = NULL; /* may be a new region, or just a copy */ + + Bool freeSrcClip = FALSE; + + RegionPtr prgnExposed = NULL; + + RegionRec rgnDst; + + int dx; + + int dy; + + int numRects; + + int box_x1; + + int box_y1; + + int box_x2; + + int box_y2; + + Bool fastSrc = FALSE; /* for fast clipping with pixmap source */ + + Bool fastDst = FALSE; /* for fast clipping with one rect dest */ + + Bool fastExpose = FALSE; /* for fast exposures with pixmap source */ + + /* Short cut for unmapped windows */ + + if (pDstDrawable->type == DRAWABLE_WINDOW && + !((WindowPtr) pDstDrawable)->realized) { + return NULL; + } + + if ((pSrcDrawable != pDstDrawable) && pSrcDrawable->pScreen->SourceValidate) { + (*pSrcDrawable->pScreen->SourceValidate) (pSrcDrawable, xIn, yIn, + widthSrc, heightSrc); + } + + /* Compute source clip region */ + if (pSrcDrawable->type == DRAWABLE_PIXMAP) { + if ((pSrcDrawable == pDstDrawable) && (pGC->clientClipType == CT_NONE)) + prgnSrcClip = fbGetCompositeClip(pGC); + else + fastSrc = TRUE; + } + else { + if (pGC->subWindowMode == IncludeInferiors) { + /* + * XFree86 DDX empties the border clip when the + * VT is inactive, make sure the region isn't empty + */ + if (!((WindowPtr) pSrcDrawable)->parent && + REGION_NOTEMPTY( + &((WindowPtr) pSrcDrawable)->borderClip)) { + /* + * special case bitblt from root window in + * IncludeInferiors mode; just like from a pixmap + */ + fastSrc = TRUE; + } + else if ((pSrcDrawable == pDstDrawable) && + (pGC->clientClipType == CT_NONE)) { + prgnSrcClip = fbGetCompositeClip(pGC); + } + else { + prgnSrcClip = NotClippedByChildren((WindowPtr) pSrcDrawable); + freeSrcClip = TRUE; + } + } + else { + prgnSrcClip = &((WindowPtr) pSrcDrawable)->clipList; + } + } + + xIn += pSrcDrawable->x; + yIn += pSrcDrawable->y; + + xOut += pDstDrawable->x; + yOut += pDstDrawable->y; + + box_x1 = xIn; + box_y1 = yIn; + box_x2 = xIn + widthSrc; + box_y2 = yIn + heightSrc; + + dx = xIn - xOut; + dy = yIn - yOut; + + /* Don't create a source region if we are doing a fast clip */ + if (fastSrc) { + RegionPtr cclip; + + fastExpose = TRUE; + /* + * clip the source; if regions extend beyond the source size, + * make sure exposure events get sent + */ + if (box_x1 < pSrcDrawable->x) { + box_x1 = pSrcDrawable->x; + fastExpose = FALSE; + } + if (box_y1 < pSrcDrawable->y) { + box_y1 = pSrcDrawable->y; + fastExpose = FALSE; + } + if (box_x2 > pSrcDrawable->x + (int) pSrcDrawable->width) { + box_x2 = pSrcDrawable->x + (int) pSrcDrawable->width; + fastExpose = FALSE; + } + if (box_y2 > pSrcDrawable->y + (int) pSrcDrawable->height) { + box_y2 = pSrcDrawable->y + (int) pSrcDrawable->height; + fastExpose = FALSE; + } + + /* Translate and clip the dst to the destination composite clip */ + box_x1 -= dx; + box_x2 -= dx; + box_y1 -= dy; + box_y2 -= dy; + + /* If the destination composite clip is one rectangle we can + do the clip directly. Otherwise we have to create a full + blown region and call intersect */ + + cclip = fbGetCompositeClip(pGC); + if (REGION_NUM_RECTS(cclip) == 1) { + BoxPtr pBox = REGION_RECTS(cclip); + + if (box_x1 < pBox->x1) + box_x1 = pBox->x1; + if (box_x2 > pBox->x2) + box_x2 = pBox->x2; + if (box_y1 < pBox->y1) + box_y1 = pBox->y1; + if (box_y2 > pBox->y2) + box_y2 = pBox->y2; + fastDst = TRUE; + } + } + + /* Check to see if the region is empty */ + if (box_x1 >= box_x2 || box_y1 >= box_y2) { + REGION_NULL(&rgnDst); + } + else { + BoxRec box; + + box.x1 = box_x1; + box.y1 = box_y1; + box.x2 = box_x2; + box.y2 = box_y2; + REGION_INIT(&rgnDst, &box, 1); + } + + /* Clip against complex source if needed */ + if (!fastSrc) { + REGION_INTERSECT(&rgnDst, &rgnDst, prgnSrcClip); + REGION_TRANSLATE(&rgnDst, -dx, -dy); + } + + /* Clip against complex dest if needed */ + if (!fastDst) { + REGION_INTERSECT(&rgnDst, &rgnDst, + fbGetCompositeClip(pGC)); + } + + /* Do bit blitting */ + numRects = REGION_NUM_RECTS(&rgnDst); + if (numRects && widthSrc && heightSrc) + fbCopyRegion(pSrcDrawable, pDstDrawable, pGC, + &rgnDst, dx, dy, copyProc, bitPlane, closure); + + /* Pixmap sources generate a NoExposed (we return NULL to do this) */ + if (!fastExpose && pGC->fExpose) + prgnExposed = miHandleExposures(pSrcDrawable, pDstDrawable, pGC, + xIn - pSrcDrawable->x, + yIn - pSrcDrawable->y, + widthSrc, heightSrc, + xOut - pDstDrawable->x, + yOut - pDstDrawable->y, + (unsigned long) bitPlane); + REGION_UNINIT(&rgnDst); + if (freeSrcClip) + REGION_DESTROY(prgnSrcClip); + fbValidateDrawable(pDstDrawable); + return prgnExposed; +} + +RegionPtr +fbCopyArea(DrawablePtr pSrcDrawable, + DrawablePtr pDstDrawable, + GCPtr pGC, + int xIn, int yIn, int widthSrc, int heightSrc, int xOut, int yOut) +{ + fbCopyProc copy; + + if (pSrcDrawable->bitsPerPixel != pDstDrawable->bitsPerPixel) + copy = fb24_32CopyMtoN; + else + copy = fbCopyNtoN; + return fbDoCopy(pSrcDrawable, pDstDrawable, pGC, xIn, yIn, + widthSrc, heightSrc, xOut, yOut, copy, 0, 0); +} + +RegionPtr +fbCopyPlane(DrawablePtr pSrcDrawable, + DrawablePtr pDstDrawable, + GCPtr pGC, + int xIn, + int yIn, + int widthSrc, + int heightSrc, int xOut, int yOut, unsigned long bitplane) +{ + if (pSrcDrawable->bitsPerPixel > 1) + return fbDoCopy(pSrcDrawable, pDstDrawable, pGC, + xIn, yIn, widthSrc, heightSrc, + xOut, yOut, fbCopyNto1, (Pixel) bitplane, 0); + else if (bitplane & 1) + return fbDoCopy(pSrcDrawable, pDstDrawable, pGC, xIn, yIn, + widthSrc, heightSrc, xOut, yOut, fbCopy1toN, + (Pixel) bitplane, 0); + else + return miHandleExposures(pSrcDrawable, pDstDrawable, pGC, + xIn, yIn, + widthSrc, heightSrc, xOut, yOut, bitplane); +} diff --git a/fb/fbedge.c b/fb/fbedge.c new file mode 100644 index 0000000..416ad26 --- /dev/null +++ b/fb/fbedge.c @@ -0,0 +1,286 @@ +/* + * + * Copyright © 2004 Keith Packard + * + * 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, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD 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. + */ + +#include + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "fb.h" + + +#include "picturestr.h" +#include "mipict.h" +#include "renderedge.h" +#include "fbpict.h" + +/* + * 4 bit alpha + */ + +#define N_BITS 4 +#define rasterizeEdges fbRasterizeEdges4 + +#if BITMAP_BIT_ORDER == LSBFirst +#define Shift4(o) ((o) << 2) +#else +#define Shift4(o) ((1-(o)) << 2) +#endif + +#define Get4(x,o) (((x) >> Shift4(o)) & 0xf) +#define Put4(x,o,v) (((x) & ~(0xf << Shift4(o))) | (((v) & 0xf) << Shift4(o))) + +#define DefineAlpha(line,x) \ + CARD8 *__ap = (CARD8 *) line + ((x) >> 1); \ + int __ao = (x) & 1 + +#define StepAlpha ((__ap += __ao), (__ao ^= 1)) + +#define AddAlpha(a) { \ + CARD8 __o = *__ap; \ + CARD8 __a = (a) + Get4(__o, __ao); \ + *__ap = Put4 (__o, __ao, __a | (0 - ((__a) >> 4))); \ +} + +#include "fbedgeimp.h" + +#undef AddAlpha +#undef StepAlpha +#undef DefineAlpha +#undef rasterizeEdges +#undef N_BITS + +/* + * 1 bit alpha + */ + +#define N_BITS 1 +#define rasterizeEdges fbRasterizeEdges1 + +#include "fbedgeimp.h" + +#undef rasterizeEdges +#undef N_BITS + +/* + * 8 bit alpha + */ + +static INLINE CARD8 +clip255(int x) +{ + if (x > 255) + return 255; + return x; +} + +static INLINE void +add_saturate_8(CARD8 *buf, int value, int length) +{ + while (length--) { + *buf = clip255(*buf + value); + buf++; + } +} + +/* + * We want to detect the case where we add the same value to a long + * span of pixels. The triangles on the end are filled in while we + * count how many sub-pixel scanlines contribute to the middle section. + * + * +--------------------------+ + * fill_height =| \ / + * +------------------+ + * |================| + * fill_start fill_end + */ +static void +fbRasterizeEdges8(FbBits * buf, + int width, + int stride, + RenderEdge * l, RenderEdge * r, xFixed t, xFixed b) +{ + xFixed y = t; + + FbBits *line; + + int fill_start = -1, fill_end = -1; + + int fill_size = 0; + + line = buf + xFixedToInt(y) * stride; + + for (;;) { + CARD8 *ap = (CARD8 *) line; + + xFixed lx, rx; + + int lxi, rxi; + + /* clip X */ + lx = l->x; + if (lx < 0) + lx = 0; + rx = r->x; + if (xFixedToInt(rx) >= width) + rx = IntToxFixed(width); + + /* Skip empty (or backwards) sections */ + if (rx > lx) { + int lxs, rxs; + + /* Find pixel bounds for span. */ + lxi = xFixedToInt(lx); + rxi = xFixedToInt(rx); + + /* Sample coverage for edge pixels */ + lxs = RenderSamplesX(lx, 8); + rxs = RenderSamplesX(rx, 8); + + /* Add coverage across row */ + if (lxi == rxi) { + ap[lxi] = clip255(ap[lxi] + rxs - lxs); + } + else { + ap[lxi] = clip255(ap[lxi] + N_X_FRAC(8) - lxs); + + /* Move forward so that lxi/rxi is the pixel span */ + lxi++; + + /* Don't bother trying to optimize the fill unless + * the span is longer than 4 pixels. */ + if (rxi - lxi > 4) { + if (fill_start < 0) { + fill_start = lxi; + fill_end = rxi; + fill_size++; + } + else { + if (lxi >= fill_end || rxi < fill_start) { + /* We're beyond what we saved, just fill it */ + add_saturate_8(ap + fill_start, + fill_size * N_X_FRAC(8), + fill_end - fill_start); + fill_start = lxi; + fill_end = rxi; + fill_size = 1; + } + else { + /* Update fill_start */ + if (lxi > fill_start) { + add_saturate_8(ap + fill_start, + fill_size * N_X_FRAC(8), + lxi - fill_start); + fill_start = lxi; + } + else if (lxi < fill_start) { + add_saturate_8(ap + lxi, N_X_FRAC(8), + fill_start - lxi); + } + + /* Update fill_end */ + if (rxi < fill_end) { + add_saturate_8(ap + rxi, + fill_size * N_X_FRAC(8), + fill_end - rxi); + fill_end = rxi; + } + else if (fill_end < rxi) { + add_saturate_8(ap + fill_end, + N_X_FRAC(8), rxi - fill_end); + } + fill_size++; + } + } + } + else { + add_saturate_8(ap + lxi, N_X_FRAC(8), rxi - lxi); + } + + /* Do not add in a 0 alpha here. This check is + * necessary to avoid a buffer overrun, (when rx + * is exactly on a pixel boundary). */ + if (rxs) + ap[rxi] = clip255(ap[rxi] + rxs); + } + } + + if (y == b) { + /* We're done, make sure we clean up any remaining fill. */ + if (fill_start != fill_end) { + if (fill_size == N_Y_FRAC(8)) { + memset(ap + fill_start, 0xff, fill_end - fill_start); + } + else { + add_saturate_8(ap + fill_start, fill_size * N_X_FRAC(8), + fill_end - fill_start); + } + } + break; + } + + if (xFixedFrac(y) != Y_FRAC_LAST(8)) { + RenderEdgeStepSmall(l); + RenderEdgeStepSmall(r); + y += STEP_Y_SMALL(8); + } + else { + RenderEdgeStepBig(l); + RenderEdgeStepBig(r); + y += STEP_Y_BIG(8); + if (fill_start != fill_end) { + if (fill_size == N_Y_FRAC(8)) { + memset(ap + fill_start, 0xff, fill_end - fill_start); + } + else { + add_saturate_8(ap + fill_start, fill_size * N_X_FRAC(8), + fill_end - fill_start); + } + fill_start = fill_end = -1; + fill_size = 0; + } + line += stride; + } + } +} + +void +fbRasterizeEdges(FbBits * buf, + int bpp, + int width, + int stride, RenderEdge * l, RenderEdge * r, xFixed t, xFixed b) +{ + switch (bpp) { + case 1: + fbRasterizeEdges1(buf, width, stride, l, r, t, b); + break; + case 4: + fbRasterizeEdges4(buf, width, stride, l, r, t, b); + break; + case 8: + fbRasterizeEdges8(buf, width, stride, l, r, t, b); + break; + } +} + diff --git a/fb/fbedgeimp.h b/fb/fbedgeimp.h new file mode 100644 index 0000000..00b5f00 --- /dev/null +++ b/fb/fbedgeimp.h @@ -0,0 +1,138 @@ +/* + * + * Copyright © 2004 Keith Packard + * + * 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, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#ifndef rasterizeSpan +#endif + +static void +rasterizeEdges(FbBits * buf, + int width, + int stride, RenderEdge * l, RenderEdge * r, xFixed t, xFixed b) +{ + xFixed y = t; + + FbBits *line; + + line = buf + xFixedToInt(y) * stride; + + for (;;) { + xFixed lx, rx; + + int lxi, rxi; + + /* clip X */ + lx = l->x; + if (lx < 0) + lx = 0; + rx = r->x; + if (xFixedToInt(rx) >= width) + rx = IntToxFixed(width); + + /* Skip empty (or backwards) sections */ + if (rx > lx) { + + /* Find pixel bounds for span */ + lxi = xFixedToInt(lx); + rxi = xFixedToInt(rx); + +#if N_BITS == 1 + { + FbBits *a = line; + + FbBits startmask, endmask; + + int nmiddle; + + int width = rxi - lxi; + + int x = lxi; + + a += x >> FB_SHIFT; + x &= FB_MASK; + + FbMaskBits(x, width, startmask, nmiddle, endmask); + if (startmask) + *a++ |= startmask; + while (nmiddle--) + *a++ = FB_ALLONES; + if (endmask) + *a |= endmask; + } +#else + { + DefineAlpha(line, lxi); + int lxs, rxs; + + /* Sample coverage for edge pixels */ + lxs = RenderSamplesX(lx, N_BITS); + rxs = RenderSamplesX(rx, N_BITS); + + /* Add coverage across row */ + if (lxi == rxi) { + AddAlpha(rxs - lxs); + } + else { + int xi; + + AddAlpha(N_X_FRAC(N_BITS) - lxs); + StepAlpha; + for (xi = lxi + 1; xi < rxi; xi++) { + AddAlpha(N_X_FRAC(N_BITS)); + StepAlpha; + } + /* Do not add in a 0 alpha here. This check is necessary + * to avoid a buffer overrun when rx is exactly on a pixel + * boundary. + */ + if (rxs != 0) + AddAlpha(rxs); + } + } +#endif + } + + if (y == b) + break; + +#if N_BITS > 1 + if (xFixedFrac(y) != Y_FRAC_LAST(N_BITS)) { + RenderEdgeStepSmall(l); + RenderEdgeStepSmall(r); + y += STEP_Y_SMALL(N_BITS); + } + else +#endif + { + RenderEdgeStepBig(l); + RenderEdgeStepBig(r); + y += STEP_Y_BIG(N_BITS); + line += stride; + } + } +} + +#undef rasterizeSpan diff --git a/fb/fbfill.c b/fb/fbfill.c new file mode 100644 index 0000000..74cfdce --- /dev/null +++ b/fb/fbfill.c @@ -0,0 +1,204 @@ +/* + * + * Copyright © 1998 Keith Packard + * + * 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, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "fb.h" + +void +fbFill(DrawablePtr pDrawable, GCPtr pGC, int x, int y, int width, int height) +{ + FbBits *dst; + + FbStride dstStride; + + int dstBpp; + + int dstXoff, dstYoff; + + FbGCPrivPtr pPriv = fbGetGCPrivate(pGC); + + fbGetDrawable(pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); + + switch (pGC->fillStyle) { + case FillSolid: + fbSolid(dst + (y + dstYoff) * dstStride, + dstStride, + (x + dstXoff) * dstBpp, + dstBpp, width * dstBpp, height, pPriv->and, pPriv->xor); + break; + case FillStippled: + case FillOpaqueStippled:{ + PixmapPtr pStip = pGC->stipple; + + int stipWidth = pStip->drawable.width; + + int stipHeight = pStip->drawable.height; + + if (dstBpp == 1) { + int alu; + + FbBits *stip; + + FbStride stipStride; + + int stipBpp; + + int stipXoff _X_UNUSED, stipYoff _X_UNUSED; + + if (pGC->fillStyle == FillStippled) + alu = FbStipple1Rop(pGC->alu, pGC->fgPixel); + else + alu = FbOpaqueStipple1Rop(pGC->alu, pGC->fgPixel, pGC->bgPixel); + fbGetDrawable(&pStip->drawable, stip, stipStride, stipBpp, stipXoff, + stipYoff); + fbTile(dst + (y + dstYoff) * dstStride, dstStride, x + dstXoff, + width, height, stip, stipStride, stipWidth, stipHeight, alu, + pPriv->pm, dstBpp, (pGC->patOrg.x + pDrawable->x + dstXoff), + pGC->patOrg.y + pDrawable->y - y); + } + else { + FbStip *stip; + + FbStride stipStride; + + int stipBpp; + + int stipXoff _X_UNUSED, stipYoff _X_UNUSED; + + FbBits fgand, fgxor, bgand, bgxor; + + fgand = pPriv->and; + fgxor = pPriv->xor; + if (pGC->fillStyle == FillStippled) { + bgand = fbAnd(GXnoop, (FbBits) 0, FB_ALLONES); + bgxor = fbXor(GXnoop, (FbBits) 0, FB_ALLONES); + } + else { + bgand = pPriv->bgand; + bgxor = pPriv->bgxor; + } + + fbGetStipDrawable(&pStip->drawable, stip, stipStride, stipBpp, + stipXoff, stipYoff); + fbStipple(dst + (y + dstYoff) * dstStride, dstStride, + (x + dstXoff) * dstBpp, dstBpp, width * dstBpp, height, + stip, stipStride, stipWidth, stipHeight, + pPriv->evenStipple, fgand, fgxor, bgand, bgxor, + pGC->patOrg.x + pDrawable->x + dstXoff, + pGC->patOrg.y + pDrawable->y - y); + } + break; + } + case FillTiled:{ + PixmapPtr pTile = pGC->tile.pixmap; + + FbBits *tile; + + FbStride tileStride; + + int tileBpp; + + int tileWidth; + + int tileHeight; + + int tileXoff _X_UNUSED, tileYoff _X_UNUSED; /* XXX assumed to be zero */ + + fbGetDrawable(&pTile->drawable, tile, tileStride, tileBpp, tileXoff, + tileYoff); + tileWidth = pTile->drawable.width; + tileHeight = pTile->drawable.height; + fbTile(dst + (y + dstYoff) * dstStride, + dstStride, + (x + dstXoff) * dstBpp, + width * dstBpp, height, + tile, + tileStride, + tileWidth * tileBpp, + tileHeight, + pGC->alu, + pPriv->pm, + dstBpp, + (pGC->patOrg.x + pDrawable->x + dstXoff) * dstBpp, + pGC->patOrg.y + pDrawable->y - y); + break; + } + } + fbValidateDrawable(pDrawable); +} + +void +fbSolidBoxClipped(DrawablePtr pDrawable, + RegionPtr pClip, + int x1, int y1, int x2, int y2, FbBits and, FbBits xor) +{ + FbBits *dst; + + FbStride dstStride; + + int dstBpp; + + int dstXoff, dstYoff; + + BoxPtr pbox; + + int nbox; + + int partX1, partX2, partY1, partY2; + + fbGetDrawable(pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); + + for (nbox = REGION_NUM_RECTS(pClip), pbox = REGION_RECTS(pClip); + nbox--; pbox++) { + partX1 = pbox->x1; + if (partX1 < x1) + partX1 = x1; + + partX2 = pbox->x2; + if (partX2 > x2) + partX2 = x2; + + if (partX2 <= partX1) + continue; + + partY1 = pbox->y1; + if (partY1 < y1) + partY1 = y1; + + partY2 = pbox->y2; + if (partY2 > y2) + partY2 = y2; + + if (partY2 <= partY1) + continue; + + fbSolid(dst + (partY1 + dstYoff) * dstStride, + dstStride, + (partX1 + dstXoff) * dstBpp, + dstBpp, + (partX2 - partX1) * dstBpp, (partY2 - partY1), and, xor); + } +} diff --git a/fb/fbfillrect.c b/fb/fbfillrect.c new file mode 100644 index 0000000..9c04fe8 --- /dev/null +++ b/fb/fbfillrect.c @@ -0,0 +1,103 @@ +/* + * Copyright © 1998 Keith Packard + * + * 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, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "fb.h" + +void +fbPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrect, xRectangle *prect) +{ + RegionPtr pClip = fbGetCompositeClip(pGC); + BoxPtr pbox; + BoxPtr pextent; + int extentX1, extentX2, extentY1, extentY2; + int fullX1, fullX2, fullY1, fullY2; + int partX1, partX2, partY1, partY2; + int xorg, yorg; + int n; + + xorg = pDrawable->x; + yorg = pDrawable->y; + + pextent = REGION_EXTENTS(pClip); + extentX1 = pextent->x1; + extentY1 = pextent->y1; + extentX2 = pextent->x2; + extentY2 = pextent->y2; + while (nrect--) { + fullX1 = prect->x + xorg; + fullY1 = prect->y + yorg; + fullX2 = fullX1 + (int) prect->width; + fullY2 = fullY1 + (int) prect->height; + prect++; + + if (fullX1 < extentX1) + fullX1 = extentX1; + + if (fullY1 < extentY1) + fullY1 = extentY1; + + if (fullX2 > extentX2) + fullX2 = extentX2; + + if (fullY2 > extentY2) + fullY2 = extentY2; + + if ((fullX1 >= fullX2) || (fullY1 >= fullY2)) + continue; + n = REGION_NUM_RECTS(pClip); + if (n == 1) { + fbFill(pDrawable, + pGC, fullX1, fullY1, fullX2 - fullX1, fullY2 - fullY1); + } + else { + pbox = REGION_RECTS(pClip); + /* + * clip the rectangle to each box in the clip region + * this is logically equivalent to calling Intersect() + */ + while (n--) { + partX1 = pbox->x1; + if (partX1 < fullX1) + partX1 = fullX1; + partY1 = pbox->y1; + if (partY1 < fullY1) + partY1 = fullY1; + partX2 = pbox->x2; + if (partX2 > fullX2) + partX2 = fullX2; + partY2 = pbox->y2; + if (partY2 > fullY2) + partY2 = fullY2; + + pbox++; + + if (partX1 < partX2 && partY1 < partY2) + fbFill(pDrawable, pGC, + partX1, partY1, partX2 - partX1, partY2 - partY1); + } + } + } +} diff --git a/fb/fbfillsp.c b/fb/fbfillsp.c new file mode 100644 index 0000000..e7e8edc --- /dev/null +++ b/fb/fbfillsp.c @@ -0,0 +1,93 @@ +/* + * + * Copyright © 1998 Keith Packard + * + * 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, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "fb.h" + +void +fbFillSpans(DrawablePtr pDrawable, + GCPtr pGC, int n, DDXPointPtr ppt, int *pwidth, int fSorted) +{ + RegionPtr pClip = fbGetCompositeClip(pGC); + + BoxPtr pextent, pbox; + + int nbox; + + int extentX1, extentX2, extentY1, extentY2; + + int fullX1, fullX2, fullY1; + + int partX1, partX2; + + pextent = REGION_EXTENTS(pClip); + extentX1 = pextent->x1; + extentY1 = pextent->y1; + extentX2 = pextent->x2; + extentY2 = pextent->y2; + while (n--) { + fullX1 = ppt->x; + fullY1 = ppt->y; + fullX2 = fullX1 + (int) *pwidth; + ppt++; + pwidth++; + + if (fullY1 < extentY1 || extentY2 <= fullY1) + continue; + + if (fullX1 < extentX1) + fullX1 = extentX1; + + if (fullX2 > extentX2) + fullX2 = extentX2; + + if (fullX1 >= fullX2) + continue; + + nbox = REGION_NUM_RECTS(pClip); + if (nbox == 1) { + fbFill(pDrawable, pGC, fullX1, fullY1, fullX2 - fullX1, 1); + } + else { + pbox = REGION_RECTS(pClip); + while (nbox--) { + if (pbox->y1 <= fullY1 && fullY1 < pbox->y2) { + partX1 = pbox->x1; + if (partX1 < fullX1) + partX1 = fullX1; + partX2 = pbox->x2; + if (partX2 > fullX2) + partX2 = fullX2; + if (partX2 > partX1) { + fbFill(pDrawable, pGC, + partX1, fullY1, partX2 - partX1, 1); + } + } + pbox++; + } + } + } +} diff --git a/fb/fbgc.c b/fb/fbgc.c new file mode 100644 index 0000000..45c437c --- /dev/null +++ b/fb/fbgc.c @@ -0,0 +1,321 @@ +/* + * + * Copyright © 1998 Keith Packard + * + * 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, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include + +#include "fb.h" + +const GCFuncs fbGCFuncs = { + fbValidateGC, + miChangeGC, + miCopyGC, + miDestroyGC, + miChangeClip, + miDestroyClip, + miCopyClip, +}; + +const GCOps fbGCOps = { + fbFillSpans, + fbSetSpans, + fbPutImage, + fbCopyArea, + fbCopyPlane, + fbPolyPoint, + fbPolyLine, + fbPolySegment, + fbPolyRectangle, + fbPolyArc, + miFillPolygon, + fbPolyFillRect, + fbPolyFillArc, + miPolyText8, + miPolyText16, + miImageText8, + miImageText16, + fbImageGlyphBlt, + fbPolyGlyphBlt, + fbPushPixels +}; + +Bool +fbCreateGC(GCPtr pGC) +{ + pGC->clientClip = NULL; + pGC->clientClipType = CT_NONE; + + pGC->ops = (GCOps *) & fbGCOps; + pGC->funcs = (GCFuncs *) & fbGCFuncs; + + /* fb wants to translate before scan conversion */ + pGC->miTranslate = 1; + + fbGetRotatedPixmap(pGC) = 0; + fbGetExpose(pGC) = 1; + fbGetFreeCompClip(pGC) = 0; + fbGetCompositeClip(pGC) = 0; + fbGetGCPrivate(pGC)->bpp = BitsPerPixel(pGC->depth); + return TRUE; +} + +/* + * Pad pixmap to FB_UNIT bits wide + */ +void +fbPadPixmap(PixmapPtr pPixmap) +{ + int width; + + FbBits *bits; + + FbBits b; + + FbBits mask; + + int height; + + int w; + + int stride; + + int bpp; + + int xOff _X_UNUSED, yOff _X_UNUSED; + + fbGetDrawable(&pPixmap->drawable, bits, stride, bpp, xOff, yOff); + + width = pPixmap->drawable.width * pPixmap->drawable.bitsPerPixel; + height = pPixmap->drawable.height; + mask = FbBitsMask(0, width); + while (height--) { + b = *bits & mask; + w = width; + while (w < FB_UNIT) { + b = b | FbScrRight(b, w); + w <<= 1; + } + *bits = b; + bits += stride; + } +} + +/* + * Verify that 'bits' repeats every 'len' bits + */ +static Bool +fbBitsRepeat(FbBits bits, int len, int width) +{ + FbBits mask = FbBitsMask(0, len); + + FbBits orig = bits & mask; + + int i; + + if (width > FB_UNIT) + width = FB_UNIT; + for (i = 0; i < width / len; i++) { + if ((bits & mask) != orig) + return FALSE; + bits = FbScrLeft(bits, len); + } + return TRUE; +} + +/* + * Check whether an entire bitmap line is a repetition of + * the first 'len' bits + */ +static Bool +fbLineRepeat(FbBits * bits, int len, int width) +{ + FbBits first = bits[0]; + + if (!fbBitsRepeat(first, len, width)) + return FALSE; + width = (width + FB_UNIT - 1) >> FB_SHIFT; + bits++; + while (--width) + if (*bits != first) + return FALSE; + return TRUE; +} + +/* + * The even stipple code wants the first FB_UNIT/bpp bits on + * each scanline to represent the entire stipple + */ +static Bool +fbCanEvenStipple(PixmapPtr pStipple, int bpp) +{ + int len = FB_UNIT / bpp; + + FbBits *bits; + + int stride; + + int stip_bpp; + + int stipXoff _X_UNUSED, stipYoff _X_UNUSED; + + int h; + + /* can't even stipple 24bpp drawables */ + if ((bpp & (bpp - 1)) != 0) + return FALSE; + /* make sure the stipple width is a multiple of the even stipple width */ + if (pStipple->drawable.width % len != 0) + return FALSE; + fbGetDrawable(&pStipple->drawable, bits, stride, stip_bpp, stipXoff, + stipYoff); + h = pStipple->drawable.height; + /* check to see that the stipple repeats horizontally */ + while (h--) { + if (!fbLineRepeat(bits, len, pStipple->drawable.width)) + return FALSE; + bits += stride; + } + return TRUE; +} + +void +fbValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable) +{ + FbGCPrivPtr pPriv = fbGetGCPrivate(pGC); + + FbBits mask; + + pGC->lastWinOrg.x = pDrawable->x; + pGC->lastWinOrg.y = pDrawable->y; + + /* + * if the client clip is different or moved OR the subwindowMode has + * changed OR the window's clip has changed since the last validation + * we need to recompute the composite clip + */ + + if ((changes & + (GCClipXOrigin | GCClipYOrigin | GCClipMask | GCSubwindowMode)) || + (pDrawable->serialNumber != (pGC->serialNumber & DRAWABLE_SERIAL_BITS)) + ) { + miComputeCompositeClip(pGC, pDrawable); + pPriv->oneRect = REGION_NUM_RECTS(fbGetCompositeClip(pGC)) == 1; + } + + if (pPriv->bpp != pDrawable->bitsPerPixel) { + changes |= GCStipple | GCForeground | GCBackground | GCPlaneMask; + pPriv->bpp = pDrawable->bitsPerPixel; + } + if ((changes & GCTile) && fbGetRotatedPixmap(pGC)) { + (*pGC->pScreen->DestroyPixmap) (fbGetRotatedPixmap(pGC)); + fbGetRotatedPixmap(pGC) = 0; + } + + if (pGC->fillStyle == FillTiled) { + PixmapPtr pOldTile, pNewTile; + + pOldTile = pGC->tile.pixmap; + if (pOldTile->drawable.bitsPerPixel != pDrawable->bitsPerPixel) { + pNewTile = fbGetRotatedPixmap(pGC); + if (!pNewTile || + pNewTile->drawable.bitsPerPixel != pDrawable->bitsPerPixel) { + if (pNewTile) + (*pGC->pScreen->DestroyPixmap) (pNewTile); + pNewTile = + fb24_32ReformatTile(pOldTile, pDrawable->bitsPerPixel); + } + if (pNewTile) { + fbGetRotatedPixmap(pGC) = pOldTile; + pGC->tile.pixmap = pNewTile; + changes |= GCTile; + } + } + } + if (changes & GCTile) { + if (!pGC->tileIsPixel && + FbEvenTile(pGC->tile.pixmap->drawable.width * + pDrawable->bitsPerPixel)) + fbPadPixmap(pGC->tile.pixmap); + } + if (changes & GCStipple) { + pPriv->evenStipple = FALSE; + + if (pGC->stipple) { + + /* can we do an even stipple ?? */ + if (FbEvenStip(pGC->stipple->drawable.width, + pDrawable->bitsPerPixel) && + (fbCanEvenStipple(pGC->stipple, pDrawable->bitsPerPixel))) + pPriv->evenStipple = TRUE; + + if (pGC->stipple->drawable.width * pDrawable->bitsPerPixel < + FB_UNIT) + fbPadPixmap(pGC->stipple); + } + } + /* + * Recompute reduced rop values + */ + if (changes & (GCForeground | GCBackground | GCPlaneMask | GCFunction)) { + int s; + + FbBits depthMask; + + mask = FbFullMask(pDrawable->bitsPerPixel); + depthMask = FbFullMask(pDrawable->depth); + + pPriv->fg = pGC->fgPixel & mask; + pPriv->bg = pGC->bgPixel & mask; + + if ((pGC->planemask & depthMask) == depthMask) + pPriv->pm = mask; + else + pPriv->pm = pGC->planemask & mask; + + s = pDrawable->bitsPerPixel; + while (s < FB_UNIT) { + pPriv->fg |= pPriv->fg << s; + pPriv->bg |= pPriv->bg << s; + pPriv->pm |= pPriv->pm << s; + s <<= 1; + } + pPriv->and = fbAnd(pGC->alu, pPriv->fg, pPriv->pm); + pPriv->xor = fbXor(pGC->alu, pPriv->fg, pPriv->pm); + pPriv->bgand = fbAnd(pGC->alu, pPriv->bg, pPriv->pm); + pPriv->bgxor = fbXor(pGC->alu, pPriv->bg, pPriv->pm); + } + if (changes & GCDashList) { + unsigned short n = pGC->numInDashList; + + unsigned char *dash = pGC->dash; + + unsigned int dashLength = 0; + + while (n--) + dashLength += (unsigned int) *dash++; + pPriv->dashLength = dashLength; + } +} diff --git a/fb/fbgetsp.c b/fb/fbgetsp.c new file mode 100644 index 0000000..46f1315 --- /dev/null +++ b/fb/fbgetsp.c @@ -0,0 +1,73 @@ +/* + * + * Copyright © 1998 Keith Packard + * + * 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, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "fb.h" + +void +fbGetSpans(DrawablePtr pDrawable, + int wMax, + DDXPointPtr ppt, int *pwidth, int nspans, char *pchardstStart) +{ + FbBits *src, *dst; + + FbStride srcStride; + + int srcBpp; + + int srcXoff, srcYoff; + + int xoff; + + /* + * XFree86 DDX empties the root borderClip when the VT is + * switched away; this checks for that case + */ + if (!fbDrawableEnabled(pDrawable)) + return; + + if (pDrawable->bitsPerPixel != BitsPerPixel(pDrawable->depth)) { + fb24_32GetSpans(pDrawable, wMax, ppt, pwidth, nspans, pchardstStart); + return; + } + + fbGetDrawable(pDrawable, src, srcStride, srcBpp, srcXoff, srcYoff); + + while (nspans--) { + xoff = (int) (((long) pchardstStart) & (FB_MASK >> 3)); + dst = (FbBits *) (pchardstStart - xoff); + xoff <<= 3; + fbBlt(src + (ppt->y + srcYoff) * srcStride, srcStride, + (ppt->x + srcXoff) * srcBpp, + dst, + 1, + xoff, + *pwidth * srcBpp, 1, GXcopy, FB_ALLONES, srcBpp, FALSE, FALSE); + pchardstStart += PixmapBytePad(*pwidth, pDrawable->depth); + ppt++; + pwidth++; + } +} diff --git a/fb/fbglyph.c b/fb/fbglyph.c new file mode 100644 index 0000000..c7dba92 --- /dev/null +++ b/fb/fbglyph.c @@ -0,0 +1,451 @@ +/* + * + * Copyright © 1998 Keith Packard + * + * 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, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "fb.h" +#include +#include "dixfontstr.h" + +#define dummyScreen screenInfo.screens[0] + +Bool +fbGlyphIn(RegionPtr pRegion, int x, int y, int width, int height) +{ + BoxRec box; + + BoxPtr pExtents = REGION_EXTENTS(pRegion); + + /* + * Check extents by hand to avoid 16 bit overflows + */ + if (x < (int) pExtents->x1) + return FALSE; + if ((int) pExtents->x2 < x + width) + return FALSE; + if (y < (int) pExtents->y1) + return FALSE; + if ((int) pExtents->y2 < y + height) + return FALSE; + box.x1 = x; + box.x2 = x + width; + box.y1 = y; + box.y2 = y + height; + return RECT_IN_REGION(pRegion, &box) == rgnIN; +} + + +#define WRITE1(d,n,fg) ((d)[n] = (CARD8) fg) +#define WRITE2(d,n,fg) (*(CARD16 *) &(d[n]) = (CARD16) fg) +#define WRITE4(d,n,fg) (*(CARD32 *) &(d[n]) = (CARD32) fg) +#if FB_UNIT == 6 && IMAGE_BYTE_ORDER == LSBFirst +#define WRITE8(d) (*(FbBits *) &(d[0]) = fg) +#else +#define WRITE8(d) WRITE4(d,0,_ABCA), WRITE4(d,4,_BCAB) +#endif + +/* + * This is a bit tricky, but it's brief. Write 12 bytes worth + * of dest, which is four pixels, at a time. This gives constant + * code for each pattern as they're always aligned the same + * + * a b c d a b c d a b c d bytes + * A B C A B C A B C A B C pixels + * + * f0 f1 f2 + * A B C A B C A B C A B C pixels LSB + * C A B C A B C A B C A B pixels MSB + * + * LSB MSB + * A f0 f1 + * B f1 f2 + * C f2 f0 + * A B f0 f2 + * B C f1 f0 + * C A f2 f1 + * A B C A f0 f1 + * B C A B f1 f2 + * C A B C f2 f0 + */ + +#undef _A +#undef _B +#undef _C +#undef _AB +#undef _BC +#undef _CA +#undef _ABCA +#undef _BCAB +#undef _CABC + +#if IMAGE_BYTE_ORDER == MSBFirst +#define _A f1 +#define _B f2 +#define _C f0 +#define _AB f2 +#define _BC f0 +#define _CA f1 +#define _ABCA f1 +#define _BCAB f2 +#define _CABC f0 +#define CASE(a,b,c,d) ((a << 3) | (b << 2) | (c << 1) | d) +#else +#define _A f0 +#define _B f1 +#define _C f2 +#define _AB f0 +#define _BC f1 +#define _CA f2 +#define _ABCA f0 +#define _BCAB f1 +#define _CABC f2 +#define CASE(a,b,c,d) (a | (b << 1) | (c << 2) | (d << 3)) +#endif + +void +fbGlyph24(FbBits * dstBits, + FbStride dstStride, + int dstBpp, FbStip * stipple, FbBits fg, int x, int height) +{ + int lshift; + + FbStip bits; + + CARD8 *dstLine; + + CARD8 *dst; + + FbStip f0, f1, f2; + + int n; + + int shift; + + f0 = fg; + f1 = FbRot24(f0, 16); + f2 = FbRot24(f0, 8); + + dstLine = (CARD8 *) dstBits; + dstLine += (x & ~3) * 3; + dstStride *= (sizeof(FbBits) / sizeof(CARD8)); + shift = x & 3; + lshift = 4 - shift; + while (height--) { + bits = *stipple++; + n = lshift; + dst = dstLine; + while (bits) { + switch (FbStipMoveLsb(FbLeftStipBits(bits, n), 4, n)) { + case CASE(0, 0, 0, 0): + break; + case CASE(1, 0, 0, 0): + WRITE2(dst, 0, _AB); + WRITE1(dst, 2, _C); + break; + case CASE(0, 1, 0, 0): + WRITE1(dst, 3, _A); + WRITE2(dst, 4, _BC); + break; + case CASE(1, 1, 0, 0): + WRITE4(dst, 0, _ABCA); + WRITE2(dst, 4, _BC); + break; + case CASE(0, 0, 1, 0): + WRITE2(dst, 6, _AB); + WRITE1(dst, 8, _C); + break; + case CASE(1, 0, 1, 0): + WRITE2(dst, 0, _AB); + WRITE1(dst, 2, _C); + + WRITE2(dst, 6, _AB); + WRITE1(dst, 8, _C); + break; + case CASE(0, 1, 1, 0): + WRITE1(dst, 3, _A); + WRITE4(dst, 4, _BCAB); + WRITE1(dst, 8, _C); + break; + case CASE(1, 1, 1, 0): + WRITE8(dst); + WRITE1(dst, 8, _C); + break; + case CASE(0, 0, 0, 1): + WRITE1(dst, 9, _A); + WRITE2(dst, 10, _BC); + break; + case CASE(1, 0, 0, 1): + WRITE2(dst, 0, _AB); + WRITE1(dst, 2, _C); + + WRITE1(dst, 9, _A); + WRITE2(dst, 10, _BC); + break; + case CASE(0, 1, 0, 1): + WRITE1(dst, 3, _A); + WRITE2(dst, 4, _BC); + + WRITE1(dst, 9, _A); + WRITE2(dst, 10, _BC); + break; + case CASE(1, 1, 0, 1): + WRITE4(dst, 0, _ABCA); + WRITE2(dst, 4, _BC); + + WRITE1(dst, 9, _A); + WRITE2(dst, 10, _BC); + break; + case CASE(0, 0, 1, 1): + WRITE2(dst, 6, _AB); + WRITE4(dst, 8, _CABC); + break; + case CASE(1, 0, 1, 1): + WRITE2(dst, 0, _AB); + WRITE1(dst, 2, _C); + + WRITE2(dst, 6, _AB); + WRITE4(dst, 8, _CABC); + break; + case CASE(0, 1, 1, 1): + WRITE1(dst, 3, _A); + WRITE4(dst, 4, _BCAB); + WRITE4(dst, 8, _CABC); + break; + case CASE(1, 1, 1, 1): + WRITE8(dst); + WRITE4(dst, 8, _CABC); + break; + } + bits = FbStipLeft(bits, n); + n = 4; + dst += 12; + } + dstLine += dstStride; + } +} + +void +fbPolyGlyphBlt(DrawablePtr pDrawable, + GCPtr pGC, + int x, + int y, + unsigned int nglyph, CharInfoPtr * ppci, pointer pglyphBase) +{ + FbGCPrivPtr pPriv = fbGetGCPrivate(pGC); + + CharInfoPtr pci; + + unsigned char *pglyph; /* pointer bits in glyph */ + + int gx, gy; + + int gWidth, gHeight; /* width and height of glyph */ + + FbStride gStride; /* stride of glyph */ + + void (*glyph) (FbBits *, FbStride, int, FbStip *, FbBits, int, int); + + FbBits *dst = 0; + + FbStride dstStride = 0; + + int dstBpp = 0; + + int dstXoff = 0, dstYoff = 0; + + glyph = 0; + if (pGC->fillStyle == FillSolid && pPriv->and == 0) { + fbGetDrawable(pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); + switch (dstBpp) { + case 8: + glyph = fbGlyph8; + break; + case 16: + glyph = fbGlyph16; + break; + case 24: + glyph = fbGlyph24; + break; + case 32: + glyph = fbGlyph32; + break; + } + } + x += pDrawable->x; + y += pDrawable->y; + + while (nglyph--) { + pci = *ppci++; + pglyph = FONTGLYPHBITS(pglyphBase, pci); + gWidth = GLYPHWIDTHPIXELS(pci); + gHeight = GLYPHHEIGHTPIXELS(pci); + if (gWidth && gHeight) { + gx = x + pci->metrics.leftSideBearing; + gy = y - pci->metrics.ascent; + if (glyph && gWidth <= sizeof(FbStip) * 8 && + fbGlyphIn(fbGetCompositeClip(pGC), gx, gy, gWidth, gHeight)) { + (*glyph) (dst + (gy + dstYoff) * dstStride, + dstStride, + dstBpp, + (FbStip *) pglyph, pPriv->xor, gx + dstXoff, gHeight); + } + else + { + gStride = GLYPHWIDTHBYTESPADDED(pci) / sizeof(FbStip); + fbPushImage(pDrawable, + pGC, + (FbStip *) pglyph, + gStride, 0, gx, gy, gWidth, gHeight); + } + } + x += pci->metrics.characterWidth; + } +} + +void +fbImageGlyphBlt(DrawablePtr pDrawable, + GCPtr pGC, + int x, + int y, + unsigned int nglyph, CharInfoPtr * ppciInit, pointer pglyphBase) +{ + FbGCPrivPtr pPriv = fbGetGCPrivate(pGC); + + CharInfoPtr *ppci; + + CharInfoPtr pci; + + unsigned char *pglyph; /* pointer bits in glyph */ + + int gWidth, gHeight; /* width and height of glyph */ + + FbStride gStride; /* stride of glyph */ + + Bool opaque; + + int n; + + int gx, gy; + + void (*glyph) (FbBits *, FbStride, int, FbStip *, FbBits, int, int); + + FbBits *dst = 0; + + FbStride dstStride = 0; + + int dstBpp = 0; + + int dstXoff = 0, dstYoff = 0; + + glyph = 0; + if (pPriv->and == 0) { + fbGetDrawable(pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); + switch (dstBpp) { + case 8: + glyph = fbGlyph8; + break; + case 16: + glyph = fbGlyph16; + break; + case 24: + glyph = fbGlyph24; + break; + case 32: + glyph = fbGlyph32; + break; + } + } + + x += pDrawable->x; + y += pDrawable->y; + + if (TERMINALFONT(pGC->font) + && !glyph + ) { + opaque = TRUE; + } + else { + int xBack, widthBack; + + int yBack, heightBack; + + ppci = ppciInit; + n = nglyph; + widthBack = 0; + while (n--) + widthBack += (*ppci++)->metrics.characterWidth; + + xBack = x; + if (widthBack < 0) { + xBack += widthBack; + widthBack = -widthBack; + } + yBack = y - FONTASCENT(pGC->font); + heightBack = FONTASCENT(pGC->font) + FONTDESCENT(pGC->font); + fbSolidBoxClipped(pDrawable, + fbGetCompositeClip(pGC), + xBack, + yBack, + xBack + widthBack, + yBack + heightBack, + fbAnd(GXcopy, pPriv->bg, pPriv->pm), + fbXor(GXcopy, pPriv->bg, pPriv->pm)); + opaque = FALSE; + } + + ppci = ppciInit; + while (nglyph--) { + pci = *ppci++; + pglyph = FONTGLYPHBITS(pglyphBase, pci); + gWidth = GLYPHWIDTHPIXELS(pci); + gHeight = GLYPHHEIGHTPIXELS(pci); + if (gWidth && gHeight) { + gx = x + pci->metrics.leftSideBearing; + gy = y - pci->metrics.ascent; + if (glyph && gWidth <= sizeof(FbStip) * 8 && + fbGlyphIn(fbGetCompositeClip(pGC), gx, gy, gWidth, gHeight)) { + (*glyph) (dst + (gy + dstYoff) * dstStride, + dstStride, + dstBpp, + (FbStip *) pglyph, pPriv->fg, gx + dstXoff, gHeight); + } + else + { + gStride = GLYPHWIDTHBYTESPADDED(pci) / sizeof(FbStip); + fbPutXYImage(pDrawable, + fbGetCompositeClip(pGC), + pPriv->fg, + pPriv->bg, + pPriv->pm, + GXcopy, + opaque, + gx, + gy, + gWidth, gHeight, (FbStip *) pglyph, gStride, 0); + } + } + x += pci->metrics.characterWidth; + } +} diff --git a/fb/fbimage.c b/fb/fbimage.c new file mode 100644 index 0000000..6a2f252 --- /dev/null +++ b/fb/fbimage.c @@ -0,0 +1,295 @@ +/* + * + * Copyright © 1998 Keith Packard + * + * 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, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include + +#include "fb.h" + +void +fbPutImage(DrawablePtr pDrawable, + GCPtr pGC, + int depth, + int x, int y, int w, int h, int leftPad, int format, char *pImage) +{ + FbGCPrivPtr pPriv = fbGetGCPrivate(pGC); + + unsigned long i; + + FbStride srcStride; + + FbStip *src = (FbStip *) pImage; + + x += pDrawable->x; + y += pDrawable->y; + + switch (format) { + case XYBitmap: + srcStride = BitmapBytePad(w + leftPad) / sizeof(FbStip); + fbPutXYImage(pDrawable, + fbGetCompositeClip(pGC), + pPriv->fg, + pPriv->bg, + pPriv->pm, + pGC->alu, TRUE, x, y, w, h, src, srcStride, leftPad); + break; + case XYPixmap: + srcStride = BitmapBytePad(w + leftPad) / sizeof(FbStip); + for (i = (unsigned long) 1 << (pDrawable->depth - 1); i; i >>= 1) { + if (i & pGC->planemask) { + fbPutXYImage(pDrawable, + fbGetCompositeClip(pGC), + FB_ALLONES, + 0, + fbReplicatePixel(i, pDrawable->bitsPerPixel), + pGC->alu, + TRUE, x, y, w, h, src, srcStride, leftPad); + src += srcStride * h; + } + } + break; + case ZPixmap: + if (pDrawable->bitsPerPixel != BitsPerPixel(pDrawable->depth)) { + srcStride = PixmapBytePad(w, pDrawable->depth); + fb24_32PutZImage(pDrawable, + fbGetCompositeClip(pGC), + pGC->alu, + (FbBits) pGC->planemask, + x, y, w, h, (CARD8 *) pImage, srcStride); + } + else + { + srcStride = PixmapBytePad(w, pDrawable->depth) / sizeof(FbStip); + fbPutZImage(pDrawable, + fbGetCompositeClip(pGC), + pGC->alu, pPriv->pm, x, y, w, h, src, srcStride); + } + } +} + +void +fbPutZImage(DrawablePtr pDrawable, + RegionPtr pClip, + int alu, + FbBits pm, + int x, + int y, int width, int height, FbStip * src, FbStride srcStride) +{ + FbStip *dst; + + FbStride dstStride; + + int dstBpp; + + int dstXoff, dstYoff; + + int nbox; + + BoxPtr pbox; + + int x1, y1, x2, y2; + + fbGetStipDrawable(pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); + + for (nbox = REGION_NUM_RECTS(pClip), + pbox = REGION_RECTS(pClip); nbox--; pbox++) { + x1 = x; + y1 = y; + x2 = x + width; + y2 = y + height; + if (x1 < pbox->x1) + x1 = pbox->x1; + if (y1 < pbox->y1) + y1 = pbox->y1; + if (x2 > pbox->x2) + x2 = pbox->x2; + if (y2 > pbox->y2) + y2 = pbox->y2; + if (x1 >= x2 || y1 >= y2) + continue; + fbBltStip(src + (y1 - y) * srcStride, + srcStride, + (x1 - x) * dstBpp, + dst + (y1 + dstYoff) * dstStride, + dstStride, + (x1 + dstXoff) * dstBpp, + (x2 - x1) * dstBpp, (y2 - y1), alu, pm, dstBpp); + } +} + +void +fbPutXYImage(DrawablePtr pDrawable, + RegionPtr pClip, + FbBits fg, + FbBits bg, + FbBits pm, + int alu, + Bool opaque, + int x, + int y, + int width, int height, FbStip * src, FbStride srcStride, int srcX) +{ + FbBits *dst; + + FbStride dstStride; + + int dstBpp; + + int dstXoff, dstYoff; + + int nbox; + + BoxPtr pbox; + + int x1, y1, x2, y2; + + FbBits fgand = 0, fgxor = 0, bgand = 0, bgxor = 0; + + fbGetDrawable(pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); + + if (dstBpp == 1) { + if (opaque) + alu = FbOpaqueStipple1Rop(alu, fg, bg); + else + alu = FbStipple1Rop(alu, fg); + } + else { + fgand = fbAnd(alu, fg, pm); + fgxor = fbXor(alu, fg, pm); + if (opaque) { + bgand = fbAnd(alu, bg, pm); + bgxor = fbXor(alu, bg, pm); + } + else { + bgand = fbAnd(GXnoop, (FbBits) 0, FB_ALLONES); + bgxor = fbXor(GXnoop, (FbBits) 0, FB_ALLONES); + } + } + + for (nbox = REGION_NUM_RECTS(pClip), + pbox = REGION_RECTS(pClip); nbox--; pbox++) { + x1 = x; + y1 = y; + x2 = x + width; + y2 = y + height; + if (x1 < pbox->x1) + x1 = pbox->x1; + if (y1 < pbox->y1) + y1 = pbox->y1; + if (x2 > pbox->x2) + x2 = pbox->x2; + if (y2 > pbox->y2) + y2 = pbox->y2; + if (x1 >= x2 || y1 >= y2) + continue; + if (dstBpp == 1) { + fbBltStip(src + (y1 - y) * srcStride, + srcStride, + (x1 - x) + srcX, + (FbStip *) (dst + (y1 + dstYoff) * dstStride), + FbBitsStrideToStipStride(dstStride), + (x1 + dstXoff) * dstBpp, + (x2 - x1) * dstBpp, (y2 - y1), alu, pm, dstBpp); + } + else { + fbBltOne(src + (y1 - y) * srcStride, + srcStride, + (x1 - x) + srcX, + dst + (y1 + dstYoff) * dstStride, + dstStride, + (x1 + dstXoff) * dstBpp, + dstBpp, + (x2 - x1) * dstBpp, (y2 - y1), fgand, fgxor, bgand, bgxor); + } + } +} + +void +fbGetImage(DrawablePtr pDrawable, + int x, + int y, + int w, int h, unsigned int format, unsigned long planeMask, char *d) +{ + FbBits *src; + + FbStride srcStride; + + int srcBpp; + + int srcXoff, srcYoff; + + FbStip *dst; + + FbStride dstStride; + + /* + * XFree86 DDX empties the root borderClip when the VT is + * switched away; this checks for that case + */ + if (!fbDrawableEnabled(pDrawable)) + return; + + if (format == ZPixmap && + pDrawable->bitsPerPixel != BitsPerPixel(pDrawable->depth)) { + fb24_32GetImage(pDrawable, x, y, w, h, format, planeMask, d); + return; + } + + fbGetDrawable(pDrawable, src, srcStride, srcBpp, srcXoff, srcYoff); + + x += pDrawable->x; + y += pDrawable->y; + + dst = (FbStip *) d; + if (format == ZPixmap || srcBpp == 1) { + FbBits pm; + + pm = fbReplicatePixel(planeMask, srcBpp); + dstStride = PixmapBytePad(w, pDrawable->depth); + if (pm != FB_ALLONES) + memset(d, 0, dstStride * h); + dstStride /= sizeof(FbStip); + fbBltStip((FbStip *) (src + (y + srcYoff) * srcStride), + FbBitsStrideToStipStride(srcStride), + (x + srcXoff) * srcBpp, + dst, dstStride, 0, w * srcBpp, h, GXcopy, pm, srcBpp); + } + else { + dstStride = BitmapBytePad(w) / sizeof(FbStip); + fbBltPlane(src + (y + srcYoff) * srcStride, + srcStride, + (x + srcXoff) * srcBpp, + srcBpp, + dst, + dstStride, + 0, + w * srcBpp, h, + fbAndStip(GXcopy, FB_STIP_ALLONES, FB_STIP_ALLONES), + fbXorStip(GXcopy, FB_STIP_ALLONES, FB_STIP_ALLONES), + fbAndStip(GXcopy, 0, FB_STIP_ALLONES), + fbXorStip(GXcopy, 0, FB_STIP_ALLONES), planeMask); + } +} diff --git a/fb/fbline.c b/fb/fbline.c new file mode 100644 index 0000000..66db935 --- /dev/null +++ b/fb/fbline.c @@ -0,0 +1,160 @@ +/* + * + * Copyright © 1998 Keith Packard + * + * 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, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "fb.h" + +void +fbZeroLine(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, DDXPointPtr ppt) +{ + int x1, y1, x2, y2; + + int x, y; + + int dashOffset; + + x = pDrawable->x; + y = pDrawable->y; + x1 = ppt->x; + y1 = ppt->y; + dashOffset = pGC->dashOffset; + while (--npt) { + ++ppt; + x2 = ppt->x; + y2 = ppt->y; + if (mode == CoordModePrevious) { + x2 += x1; + y2 += y1; + } + fbSegment(pDrawable, pGC, x1 + x, y1 + y, + x2 + x, y2 + y, + npt == 1 && pGC->capStyle != CapNotLast, &dashOffset); + x1 = x2; + y1 = y2; + } +} + +void +fbZeroSegment(DrawablePtr pDrawable, GCPtr pGC, int nseg, xSegment * pSegs) +{ + int dashOffset; + + int x, y; + + Bool drawLast = pGC->capStyle != CapNotLast; + + x = pDrawable->x; + y = pDrawable->y; + while (nseg--) { + dashOffset = pGC->dashOffset; + fbSegment(pDrawable, pGC, + pSegs->x1 + x, pSegs->y1 + y, + pSegs->x2 + x, pSegs->y2 + y, drawLast, &dashOffset); + pSegs++; + } +} + +void +fbFixCoordModePrevious(int npt, DDXPointPtr ppt) +{ + int x, y; + + x = ppt->x; + y = ppt->y; + npt--; + while (npt--) { + ppt++; + x = (ppt->x += x); + y = (ppt->y += y); + } +} + +void +fbPolyLine(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, DDXPointPtr ppt) +{ + void (*line) (DrawablePtr, GCPtr, int mode, int npt, DDXPointPtr ppt); + + if (pGC->lineWidth == 0) { + line = fbZeroLine; + if (pGC->fillStyle == FillSolid && + pGC->lineStyle == LineSolid && + REGION_NUM_RECTS(fbGetCompositeClip(pGC)) == 1) { + switch (pDrawable->bitsPerPixel) { + case 8: + line = fbPolyline8; + break; + case 16: + line = fbPolyline16; + break; + case 24: + line = fbPolyline24; + break; + case 32: + line = fbPolyline32; + break; + } + } + } + else { + if (pGC->lineStyle != LineSolid) + line = miWideDash; + else + line = miWideLine; + } + (*line) (pDrawable, pGC, mode, npt, ppt); +} + +void +fbPolySegment(DrawablePtr pDrawable, GCPtr pGC, int nseg, xSegment * pseg) +{ + void (*seg) (DrawablePtr pDrawable, GCPtr pGC, int nseg, xSegment * pseg); + + if (pGC->lineWidth == 0) { + seg = fbZeroSegment; + if (pGC->fillStyle == FillSolid && + pGC->lineStyle == LineSolid && + REGION_NUM_RECTS(fbGetCompositeClip(pGC)) == 1) { + switch (pDrawable->bitsPerPixel) { + case 8: + seg = fbPolySegment8; + break; + case 16: + seg = fbPolySegment16; + break; + case 24: + seg = fbPolySegment24; + break; + case 32: + seg = fbPolySegment32; + break; + } + } + } + else { + seg = miPolySegment; + } + (*seg) (pDrawable, pGC, nseg, pseg); +} diff --git a/fb/fboverlay.c b/fb/fboverlay.c new file mode 100644 index 0000000..005a08c --- /dev/null +++ b/fb/fboverlay.c @@ -0,0 +1,424 @@ +/* + * + * Copyright © 2000 SuSE, 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, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * 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. + * + * Author: Keith Packard, SuSE, Inc. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include + +#include "fb.h" +#include "fboverlay.h" +#include "shmint.h" + +int fbOverlayGeneration; + +static int fbOverlayScreenPrivateIndex = -1; + +int +fbOverlayGetScreenPrivateIndex(void) +{ + return fbOverlayScreenPrivateIndex; +} + +/* + * Replace this if you want something supporting + * multiple overlays with the same depth + */ +Bool +fbOverlayCreateWindow(WindowPtr pWin) +{ + FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pWin->drawable.pScreen); + + int i; + + PixmapPtr pPixmap; + + if (pWin->drawable.class != InputOutput) + return TRUE; + + if (pWin->drawable.bitsPerPixel == 32) + pWin->drawable.bitsPerPixel = + fbGetScreenPrivate(pWin->drawable.pScreen)->win32bpp; + + for (i = 0; i < pScrPriv->nlayers; i++) { + pPixmap = pScrPriv->layer[i].u.run.pixmap; + if (pWin->drawable.depth == pPixmap->drawable.depth) { + pWin->devPrivates[fbWinPrivateIndex].ptr = (pointer) pPixmap; + /* + * Make sure layer keys are written correctly by + * having non-root layers set to full while the + * root layer is set to empty. This will cause + * all of the layers to get painted when the root + * is mapped + */ + if (!pWin->parent) { + REGION_EMPTY( + &pScrPriv->layer[i].u.run.region); + } + return TRUE; + } + } + return FALSE; +} + +Bool +fbOverlayCloseScreen(int iScreen, ScreenPtr pScreen) +{ + FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pScreen); + + int i; + + for (i = 0; i < pScrPriv->nlayers; i++) { + (*pScreen->DestroyPixmap) (pScrPriv->layer[i].u.run.pixmap); + REGION_UNINIT(&pScrPriv->layer[i].u.run.region); + } + return TRUE; +} + +/* + * Return layer containing this window + */ +int +fbOverlayWindowLayer(WindowPtr pWin) +{ + FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pWin->drawable.pScreen); + + int i; + + for (i = 0; i < pScrPriv->nlayers; i++) + if (pWin->devPrivates[fbWinPrivateIndex].ptr == + (pointer) pScrPriv->layer[i].u.run.pixmap) + return i; + return 0; +} + +Bool +fbOverlayCreateScreenResources(ScreenPtr pScreen) +{ + int i; + + FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pScreen); + + PixmapPtr pPixmap; + + pointer pbits; + + int width; + + int depth; + + BoxRec box; + + if (!miCreateScreenResources(pScreen)) + return FALSE; + + box.x1 = 0; + box.y1 = 0; + box.x2 = pScreen->width; + box.y2 = pScreen->height; + for (i = 0; i < pScrPriv->nlayers; i++) { + pbits = pScrPriv->layer[i].u.init.pbits; + width = pScrPriv->layer[i].u.init.width; + depth = pScrPriv->layer[i].u.init.depth; + pPixmap = (*pScreen->CreatePixmap) (pScreen, 0, 0, depth); + if (!pPixmap) + return FALSE; + if (!(*pScreen->ModifyPixmapHeader) (pPixmap, pScreen->width, + pScreen->height, depth, + BitsPerPixel(depth), + PixmapBytePad(width, depth), + pbits)) + return FALSE; + pScrPriv->layer[i].u.run.pixmap = pPixmap; + REGION_INIT(&pScrPriv->layer[i].u.run.region, &box, 0); + } + pScreen->devPrivate = pScrPriv->layer[0].u.run.pixmap; + return TRUE; +} + +void +fbOverlayPaintKey(DrawablePtr pDrawable, + RegionPtr pRegion, CARD32 pixel, int layer) +{ + fbFillRegionSolid(pDrawable, pRegion, 0, + fbReplicatePixel(pixel, pDrawable->bitsPerPixel)); +} + +/* + * Track visible region for each layer + */ +void +fbOverlayUpdateLayerRegion(ScreenPtr pScreen, int layer, RegionPtr prgn) +{ + FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pScreen); + + int i; + + RegionRec rgnNew; + + if (!prgn || !REGION_NOTEMPTY(prgn)) + return; + for (i = 0; i < pScrPriv->nlayers; i++) { + if (i == layer) { + /* add new piece to this fb */ + REGION_UNION(&pScrPriv->layer[i].u.run.region, + &pScrPriv->layer[i].u.run.region, prgn); + } + else if (REGION_NOTEMPTY(&pScrPriv->layer[i].u.run.region)) { + /* paint new piece with chroma key */ + REGION_NULL(&rgnNew); + REGION_INTERSECT(&rgnNew, prgn, &pScrPriv->layer[i].u.run.region); + (*pScrPriv->PaintKey) (&pScrPriv->layer[i].u.run.pixmap->drawable, + &rgnNew, pScrPriv->layer[i].key, i); + REGION_UNINIT(&rgnNew); + /* remove piece from other fbs */ + REGION_SUBTRACT( + &pScrPriv->layer[i].u.run.region, + &pScrPriv->layer[i].u.run.region, prgn); + } + } +} + +/* + * Copy only areas in each layer containing real bits + */ +void +fbOverlayCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + + FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pWin->drawable.pScreen); + + RegionRec rgnDst; + + int dx, dy; + + int i; + + RegionRec layerRgn[FB_OVERLAY_MAX]; + + PixmapPtr pPixmap; + + dx = ptOldOrg.x - pWin->drawable.x; + dy = ptOldOrg.y - pWin->drawable.y; + + /* + * Clip to existing bits + */ + REGION_TRANSLATE(prgnSrc, -dx, -dy); + REGION_NULL(&rgnDst); + REGION_INTERSECT(&rgnDst, &pWin->borderClip, prgnSrc); + REGION_TRANSLATE(&rgnDst, dx, dy); + /* + * Compute the portion of each fb affected by this copy + */ + for (i = 0; i < pScrPriv->nlayers; i++) { + REGION_NULL(&layerRgn[i]); + REGION_INTERSECT(&layerRgn[i], &rgnDst, + &pScrPriv->layer[i].u.run.region); + if (REGION_NOTEMPTY(&layerRgn[i])) { + REGION_TRANSLATE(&layerRgn[i], -dx, -dy); + pPixmap = pScrPriv->layer[i].u.run.pixmap; + fbCopyRegion(&pPixmap->drawable, &pPixmap->drawable, + 0, + &layerRgn[i], dx, dy, pScrPriv->CopyWindow, 0, + (void *) (long) i); + } + } + /* + * Update regions + */ + for (i = 0; i < pScrPriv->nlayers; i++) { + if (REGION_NOTEMPTY(&layerRgn[i])) + fbOverlayUpdateLayerRegion(pScreen, i, &layerRgn[i]); + + REGION_UNINIT(&layerRgn[i]); + } + REGION_UNINIT(&rgnDst); +} + +void +fbOverlayWindowExposures(WindowPtr pWin, + RegionPtr prgn, RegionPtr other_exposed) +{ + fbOverlayUpdateLayerRegion(pWin->drawable.pScreen, + fbOverlayWindowLayer(pWin), prgn); + miWindowExposures(pWin, prgn, other_exposed); +} + +void +fbOverlayPaintWindow(WindowPtr pWin, RegionPtr pRegion, int what) +{ + if (what == PW_BORDER) + fbOverlayUpdateLayerRegion(pWin->drawable.pScreen, + fbOverlayWindowLayer(pWin), pRegion); + fbPaintWindow(pWin, pRegion, what); +} + +Bool +fbOverlaySetupScreen(ScreenPtr pScreen, + pointer pbits1, + pointer pbits2, + int xsize, + int ysize, + int dpix, + int dpiy, int width1, int width2, int bpp1, int bpp2) +{ + return fbSetupScreen(pScreen, + pbits1, xsize, ysize, dpix, dpiy, width1, bpp1); +} + +static Bool +fb24_32OverlayCreateScreenResources(ScreenPtr pScreen) +{ + FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pScreen); + + int pitch; + + Bool retval; + + int i; + + if ((retval = fbOverlayCreateScreenResources(pScreen))) { + for (i = 0; i < pScrPriv->nlayers; i++) { + /* fix the screen pixmap */ + PixmapPtr pPix = (PixmapPtr) pScrPriv->layer[i].u.run.pixmap; + + if (pPix->drawable.bitsPerPixel == 32) { + pPix->drawable.bitsPerPixel = 24; + pitch = BitmapBytePad(pPix->drawable.width * 24); + pPix->devKind = pitch; + } + } + } + + return retval; +} + +Bool +fbOverlayFinishScreenInit(ScreenPtr pScreen, + pointer pbits1, + pointer pbits2, + int xsize, + int ysize, + int dpix, + int dpiy, + int width1, + int width2, + int bpp1, int bpp2, int depth1, int depth2) +{ + VisualPtr visuals; + + DepthPtr depths; + + int nvisuals; + + int ndepths; + + int bpp = 0, imagebpp = 32; + + VisualID defaultVisual; + + FbOverlayScrPrivPtr pScrPriv; + + if (fbOverlayGeneration != serverGeneration) { + fbOverlayScreenPrivateIndex = AllocateScreenPrivateIndex(); + fbOverlayGeneration = serverGeneration; + } + + pScrPriv = malloc(sizeof(FbOverlayScrPrivRec)); + if (!pScrPriv) + return FALSE; + + if (bpp1 == 32 || bpp2 == 32) + bpp = 32; + else if (bpp1 == 24 || bpp2 == 24) + bpp = 24; + + if (bpp == 24) { + int f; + + imagebpp = 32; + /* + * Check to see if we're advertising a 24bpp image format, + * in which case windows will use it in preference to a 32 bit + * format. + */ + for (f = 0; f < screenInfo.numPixmapFormats; f++) { + if (screenInfo.formats[f].bitsPerPixel == 24) { + imagebpp = 24; + break; + } + } + } + if (imagebpp == 32) { + fbGetScreenPrivate(pScreen)->win32bpp = bpp; + fbGetScreenPrivate(pScreen)->pix32bpp = bpp; + } + else { + fbGetScreenPrivate(pScreen)->win32bpp = 32; + fbGetScreenPrivate(pScreen)->pix32bpp = 32; + } + + if (!fbInitVisuals(&visuals, &depths, &nvisuals, &ndepths, &depth1, + &defaultVisual, ((unsigned long) 1 << (bpp1 - 1)) | + ((unsigned long) 1 << (bpp2 - 1)), 8)) + return FALSE; + if (!miScreenInit(pScreen, 0, xsize, ysize, dpix, dpiy, 0, + depth1, ndepths, depths, defaultVisual, nvisuals, visuals + )) + return FALSE; + /* MI thinks there's no frame buffer */ + ShmRegisterFbFuncs(pScreen); + pScreen->minInstalledCmaps = 1; + pScreen->maxInstalledCmaps = 2; + + pScrPriv->nlayers = 2; + pScrPriv->PaintKey = fbOverlayPaintKey; + pScrPriv->CopyWindow = fbCopyWindowProc; + pScrPriv->layer[0].u.init.pbits = pbits1; + pScrPriv->layer[0].u.init.width = width1; + pScrPriv->layer[0].u.init.depth = depth1; + + pScrPriv->layer[1].u.init.pbits = pbits2; + pScrPriv->layer[1].u.init.width = width2; + pScrPriv->layer[1].u.init.depth = depth2; + + pScreen->devPrivates[fbOverlayScreenPrivateIndex].ptr = (pointer) pScrPriv; + + /* overwrite miCloseScreen with our own */ + pScreen->CloseScreen = fbOverlayCloseScreen; + pScreen->CreateScreenResources = fbOverlayCreateScreenResources; + pScreen->CreateWindow = fbOverlayCreateWindow; + pScreen->WindowExposures = fbOverlayWindowExposures; + pScreen->CopyWindow = fbOverlayCopyWindow; + pScreen->PaintWindowBorder = fbOverlayPaintWindow; + if (bpp == 24 && imagebpp == 32) { + pScreen->ModifyPixmapHeader = fb24_32ModifyPixmapHeader; + pScreen->CreateScreenResources = fb24_32OverlayCreateScreenResources; + } + + return TRUE; +} diff --git a/fb/fboverlay.h b/fb/fboverlay.h new file mode 100644 index 0000000..8b5d5fa --- /dev/null +++ b/fb/fboverlay.h @@ -0,0 +1,116 @@ +/* + * + * Copyright © 2000 SuSE, 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, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * 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. + * + * Author: Keith Packard, SuSE, Inc. + */ + +#ifndef _FBOVERLAY_H_ +#define _FBOVERLAY_H_ + +extern int fbOverlayGeneration; + +extern int fbOverlayGetScreenPrivateIndex(void); + +#ifndef FB_OVERLAY_MAX +#define FB_OVERLAY_MAX 2 +#endif + +typedef void (*fbOverlayPaintKeyProc) (DrawablePtr, RegionPtr, CARD32, int); + +typedef struct _fbOverlayLayer { + union { + struct { + pointer pbits; + int width; + int depth; + } init; + struct { + PixmapPtr pixmap; + RegionRec region; + } run; + } u; + CARD32 key; /* special pixel value */ +} FbOverlayLayer; + +typedef struct _fbOverlayScrPriv { + int nlayers; + fbOverlayPaintKeyProc PaintKey; + fbCopyProc CopyWindow; + FbOverlayLayer layer[FB_OVERLAY_MAX]; +} FbOverlayScrPrivRec, *FbOverlayScrPrivPtr; + +#define fbOverlayGetScrPriv(s) \ + ((fbOverlayGetScreenPrivateIndex() != -1) ? \ + (s)->devPrivates[fbOverlayGetScreenPrivateIndex()].ptr : NULL) +Bool + fbOverlayCreateWindow(WindowPtr pWin); + +Bool + fbOverlayCloseScreen(int iScreen, ScreenPtr pScreen); + +int + fbOverlayWindowLayer(WindowPtr pWin); + +Bool + fbOverlayCreateScreenResources(ScreenPtr pScreen); + +void + +fbOverlayPaintKey(DrawablePtr pDrawable, + RegionPtr pRegion, CARD32 pixel, int layer); +void + fbOverlayUpdateLayerRegion(ScreenPtr pScreen, int layer, RegionPtr prgn); + +void + fbOverlayCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc); + +void + +fbOverlayWindowExposures(WindowPtr pWin, + RegionPtr prgn, RegionPtr other_exposed); + +void + fbOverlayPaintWindow(WindowPtr pWin, RegionPtr pRegion, int what); + +Bool + +fbOverlaySetupScreen(ScreenPtr pScreen, + pointer pbits1, + pointer pbits2, + int xsize, + int ysize, + int dpix, + int dpiy, int width1, int width2, int bpp1, int bpp2); + +Bool + +fbOverlayFinishScreenInit(ScreenPtr pScreen, + pointer pbits1, + pointer pbits2, + int xsize, + int ysize, + int dpix, + int dpiy, + int width1, + int width2, + int bpp1, int bpp2, int depth1, int depth2); + +#endif /* _FBOVERLAY_H_ */ diff --git a/fb/fbpict.c b/fb/fbpict.c new file mode 100644 index 0000000..a1a55c0 --- /dev/null +++ b/fb/fbpict.c @@ -0,0 +1,1240 @@ +/* + * + * Copyright © 2000 SuSE, 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, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * 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. + * + * Author: Keith Packard, SuSE, Inc. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include + +#include "fb.h" + + +#include "picturestr.h" +#include "mipict.h" +#include "fbpict.h" + +typedef void (*CompositeFunc) (CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, CARD16 width, CARD16 height); + +CARD32 +fbOver(CARD32 x, CARD32 y) +{ + CARD16 a = ~x >> 24; + + CARD16 t; + + CARD32 m, n, o, p; + + m = FbOverU(x, y, 0, a, t); + n = FbOverU(x, y, 8, a, t); + o = FbOverU(x, y, 16, a, t); + p = FbOverU(x, y, 24, a, t); + return m | n | o | p; +} + +CARD32 +fbOver24(CARD32 x, CARD32 y) +{ + CARD16 a = ~x >> 24; + + CARD16 t; + + CARD32 m, n, o; + + m = FbOverU(x, y, 0, a, t); + n = FbOverU(x, y, 8, a, t); + o = FbOverU(x, y, 16, a, t); + return m | n | o; +} + +CARD32 +fbIn(CARD32 x, CARD8 y) +{ + CARD16 a = y; + + CARD16 t; + + CARD32 m, n, o, p; + + m = FbInU(x, 0, a, t); + n = FbInU(x, 8, a, t); + o = FbInU(x, 16, a, t); + p = FbInU(x, 24, a, t); + return m | n | o | p; +} + +/* + * Naming convention: + * + * opSRCxMASKxDST + */ + +void +fbCompositeSolidMask_nx8x8888(CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, CARD16 width, CARD16 height) +{ + CARD32 src, srca; + + CARD32 *dstLine, *dst, d, dstMask; + + CARD8 *maskLine, *mask, m; + + FbStride dstStride, maskStride; + + CARD16 w; + + fbComposeGetSolid(pSrc, src, pDst->format); + + dstMask = FbFullMask(pDst->pDrawable->depth); + srca = src >> 24; + if (src == 0) + return; + + fbComposeGetStart(pDst, xDst, yDst, CARD32, dstStride, dstLine, 1); + fbComposeGetStart(pMask, xMask, yMask, CARD8, maskStride, maskLine, 1); + + while (height--) { + dst = dstLine; + dstLine += dstStride; + mask = maskLine; + maskLine += maskStride; + w = width; + + while (w--) { + m = *mask++; + if (m == 0xff) { + if (srca == 0xff) + *dst = src & dstMask; + else + *dst = fbOver(src, *dst) & dstMask; + } + else if (m) { + d = fbIn(src, m); + *dst = fbOver(d, *dst) & dstMask; + } + dst++; + } + } +} + +void +fbCompositeSolidMask_nx8888x8888C(CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, CARD16 width, CARD16 height) +{ + CARD32 src, srca; + + CARD32 *dstLine, *dst, d, dstMask; + + CARD32 *maskLine, *mask, ma; + + FbStride dstStride, maskStride; + + CARD16 w; + + CARD32 m, n, o, p; + + fbComposeGetSolid(pSrc, src, pDst->format); + + dstMask = FbFullMask(pDst->pDrawable->depth); + srca = src >> 24; + if (src == 0) + return; + + fbComposeGetStart(pDst, xDst, yDst, CARD32, dstStride, dstLine, 1); + fbComposeGetStart(pMask, xMask, yMask, CARD32, maskStride, maskLine, 1); + + while (height--) { + dst = dstLine; + dstLine += dstStride; + mask = maskLine; + maskLine += maskStride; + w = width; + + while (w--) { + ma = *mask++; + if (ma == 0xffffffff) { + if (srca == 0xff) + *dst = src & dstMask; + else + *dst = fbOver(src, *dst) & dstMask; + } + else if (ma) { + d = *dst; +#define FbInOverC(src,srca,msk,dst,i,result) { \ + CARD16 __a = FbGet8(msk,i); \ + CARD32 __t, __ta; \ + CARD32 __i; \ + __t = FbIntMult (FbGet8(src,i), __a,__i); \ + __ta = (CARD8) ~FbIntMult (srca, __a,__i); \ + __t = __t + FbIntMult(FbGet8(dst,i),__ta,__i); \ + __t = (CARD32) (CARD8) (__t | (-(__t >> 8))); \ + result = __t << (i); \ +} + FbInOverC(src, srca, ma, d, 0, m); + FbInOverC(src, srca, ma, d, 8, n); + FbInOverC(src, srca, ma, d, 16, o); + FbInOverC(src, srca, ma, d, 24, p); + *dst = m | n | o | p; + } + dst++; + } + } +} + +void +fbCompositeSolidMask_nx8x0888(CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, CARD16 width, CARD16 height) +{ + CARD32 src, srca; + + CARD8 *dstLine, *dst; + + CARD32 d; + + CARD8 *maskLine, *mask, m; + + FbStride dstStride, maskStride; + + CARD16 w; + + fbComposeGetSolid(pSrc, src, pDst->format); + + srca = src >> 24; + if (src == 0) + return; + + fbComposeGetStart(pDst, xDst, yDst, CARD8, dstStride, dstLine, 3); + fbComposeGetStart(pMask, xMask, yMask, CARD8, maskStride, maskLine, 1); + + while (height--) { + dst = dstLine; + dstLine += dstStride; + mask = maskLine; + maskLine += maskStride; + w = width; + + while (w--) { + m = *mask++; + if (m == 0xff) { + if (srca == 0xff) + d = src; + else { + d = Fetch24(dst); + d = fbOver24(src, d); + } + Store24(dst, d); + } + else if (m) { + d = fbOver24(fbIn(src, m), Fetch24(dst)); + Store24(dst, d); + } + dst += 3; + } + } +} + +void +fbCompositeSolidMask_nx8x0565(CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, CARD16 width, CARD16 height) +{ + CARD32 src, srca; + + CARD16 *dstLine, *dst; + + CARD32 d; + + CARD8 *maskLine, *mask, m; + + FbStride dstStride, maskStride; + + CARD16 w; + + fbComposeGetSolid(pSrc, src, pDst->format); + + srca = src >> 24; + if (src == 0) + return; + + fbComposeGetStart(pDst, xDst, yDst, CARD16, dstStride, dstLine, 1); + fbComposeGetStart(pMask, xMask, yMask, CARD8, maskStride, maskLine, 1); + + while (height--) { + dst = dstLine; + dstLine += dstStride; + mask = maskLine; + maskLine += maskStride; + w = width; + + while (w--) { + m = *mask++; + if (m == 0xff) { + if (srca == 0xff) + d = src; + else { + d = *dst; + d = fbOver24(src, cvt0565to8888(d)); + } + *dst = cvt8888to0565(d); + } + else if (m) { + d = *dst; + d = fbOver24(fbIn(src, m), cvt0565to8888(d)); + *dst = cvt8888to0565(d); + } + dst++; + } + } +} + +void +fbCompositeSolidMask_nx8888x0565C(CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, CARD16 width, CARD16 height) +{ + CARD32 src, srca; + + CARD16 src16; + + CARD16 *dstLine, *dst; + + CARD32 d; + + CARD32 *maskLine, *mask, ma; + + FbStride dstStride, maskStride; + + CARD16 w; + + CARD32 m, n, o; + + fbComposeGetSolid(pSrc, src, pDst->format); + + srca = src >> 24; + if (src == 0) + return; + + src16 = cvt8888to0565(src); + + fbComposeGetStart(pDst, xDst, yDst, CARD16, dstStride, dstLine, 1); + fbComposeGetStart(pMask, xMask, yMask, CARD32, maskStride, maskLine, 1); + + while (height--) { + dst = dstLine; + dstLine += dstStride; + mask = maskLine; + maskLine += maskStride; + w = width; + + while (w--) { + ma = *mask++; + if (ma == 0xffffffff) { + if (srca == 0xff) { + *dst = src16; + } + else { + d = *dst; + d = fbOver24(src, cvt0565to8888(d)); + *dst = cvt8888to0565(d); + } + } + else if (ma) { + d = *dst; + d = cvt0565to8888(d); + FbInOverC(src, srca, ma, d, 0, m); + FbInOverC(src, srca, ma, d, 8, n); + FbInOverC(src, srca, ma, d, 16, o); + d = m | n | o; + *dst = cvt8888to0565(d); + } + dst++; + } + } +} + +void +fbCompositeSrc_8888x8888(CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, INT16 yDst, CARD16 width, CARD16 height) +{ + CARD32 *dstLine, *dst, dstMask; + + CARD32 *srcLine, *src, s; + + FbStride dstStride, srcStride; + + CARD8 a; + + CARD16 w; + + fbComposeGetStart(pDst, xDst, yDst, CARD32, dstStride, dstLine, 1); + + fbComposeGetStart(pSrc, xSrc, ySrc, CARD32, srcStride, srcLine, 1); + + dstMask = FbFullMask(pDst->pDrawable->depth); + + while (height--) { + dst = dstLine; + dstLine += dstStride; + src = srcLine; + srcLine += srcStride; + w = width; + + while (w--) { + s = *src++; + a = s >> 24; + if (a == 0xff) + *dst = s & dstMask; + else if (a) + *dst = fbOver(s, *dst) & dstMask; + dst++; + } + } +} + +void +fbCompositeSrc_8888x0888(CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, INT16 yDst, CARD16 width, CARD16 height) +{ + CARD8 *dstLine, *dst; + + CARD32 d; + + CARD32 *srcLine, *src, s; + + CARD8 a; + + FbStride dstStride, srcStride; + + CARD16 w; + + fbComposeGetStart(pDst, xDst, yDst, CARD8, dstStride, dstLine, 3); + + fbComposeGetStart(pSrc, xSrc, ySrc, CARD32, srcStride, srcLine, 1); + + while (height--) { + dst = dstLine; + dstLine += dstStride; + src = srcLine; + srcLine += srcStride; + w = width; + + while (w--) { + s = *src++; + a = s >> 24; + if (a) { + if (a == 0xff) + d = s; + else + d = fbOver24(s, Fetch24(dst)); + Store24(dst, d); + } + dst += 3; + } + } +} + +void +fbCompositeSrc_8888x0565(CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, INT16 yDst, CARD16 width, CARD16 height) +{ + CARD16 *dstLine, *dst; + + CARD32 d; + + CARD32 *srcLine, *src, s; + + CARD8 a; + + FbStride dstStride, srcStride; + + CARD16 w; + + fbComposeGetStart(pSrc, xSrc, ySrc, CARD32, srcStride, srcLine, 1); + + fbComposeGetStart(pDst, xDst, yDst, CARD16, dstStride, dstLine, 1); + + while (height--) { + dst = dstLine; + dstLine += dstStride; + src = srcLine; + srcLine += srcStride; + w = width; + + while (w--) { + s = *src++; + a = s >> 24; + if (a) { + if (a == 0xff) + d = s; + else { + d = *dst; + d = fbOver24(s, cvt0565to8888(d)); + } + *dst = cvt8888to0565(d); + } + dst++; + } + } +} + +void +fbCompositeSrc_0565x0565(CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, INT16 yDst, CARD16 width, CARD16 height) +{ + CARD16 *dstLine, *dst; + + CARD16 *srcLine, *src; + + FbStride dstStride, srcStride; + + CARD16 w; + + fbComposeGetStart(pSrc, xSrc, ySrc, CARD16, srcStride, srcLine, 1); + + fbComposeGetStart(pDst, xDst, yDst, CARD16, dstStride, dstLine, 1); + + while (height--) { + dst = dstLine; + dstLine += dstStride; + src = srcLine; + srcLine += srcStride; + w = width; + + while (w--) + *dst++ = *src++; + } +} + +void +fbCompositeSrcAdd_8000x8000(CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, INT16 yDst, CARD16 width, CARD16 height) +{ + CARD8 *dstLine, *dst; + + CARD8 *srcLine, *src; + + FbStride dstStride, srcStride; + + CARD16 w; + + CARD8 s, d; + + CARD16 t; + + fbComposeGetStart(pSrc, xSrc, ySrc, CARD8, srcStride, srcLine, 1); + + fbComposeGetStart(pDst, xDst, yDst, CARD8, dstStride, dstLine, 1); + + while (height--) { + dst = dstLine; + dstLine += dstStride; + src = srcLine; + srcLine += srcStride; + w = width; + + while (w--) { + s = *src++; + if (s) { + if (s != 0xff) { + d = *dst; + t = d + s; + s = t | (0 - (t >> 8)); + } + *dst = s; + } + dst++; + } + } +} + +void +fbCompositeSrcAdd_8888x8888(CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, INT16 yDst, CARD16 width, CARD16 height) +{ + CARD32 *dstLine, *dst; + + CARD32 *srcLine, *src; + + FbStride dstStride, srcStride; + + CARD16 w; + + CARD32 s, d; + + CARD16 t; + + CARD32 m, n, o, p; + + fbComposeGetStart(pSrc, xSrc, ySrc, CARD32, srcStride, srcLine, 1); + + fbComposeGetStart(pDst, xDst, yDst, CARD32, dstStride, dstLine, 1); + + while (height--) { + dst = dstLine; + dstLine += dstStride; + src = srcLine; + srcLine += srcStride; + w = width; + + while (w--) { + s = *src++; + if (s) { + if (s != 0xffffffff) { + d = *dst; + if (d) { + m = FbAdd(s, d, 0, t); + n = FbAdd(s, d, 8, t); + o = FbAdd(s, d, 16, t); + p = FbAdd(s, d, 24, t); + s = m | n | o | p; + } + } + *dst = s; + } + dst++; + } + } +} + +void +fbCompositeSrcAdd_1000x1000(CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, INT16 yDst, CARD16 width, CARD16 height) +{ + FbBits *dstBits, *srcBits; + + FbStride dstStride, srcStride; + + int dstBpp, srcBpp; + + int dstXoff, dstYoff; + + int srcXoff, srcYoff; + + fbGetDrawable(pSrc->pDrawable, srcBits, srcStride, srcBpp, srcXoff, + srcYoff); + + fbGetDrawable(pDst->pDrawable, dstBits, dstStride, dstBpp, dstXoff, + dstYoff); + + fbBlt(srcBits + srcStride * (ySrc + srcYoff), + srcStride, + xSrc + srcXoff, + dstBits + dstStride * (yDst + dstYoff), + dstStride, + xDst + dstXoff, + width, height, GXor, FB_ALLONES, srcBpp, FALSE, FALSE); +} + +void +fbCompositeSolidMask_nx1xn(CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, INT16 yDst, CARD16 width, CARD16 height) +{ + FbBits *dstBits; + + FbStip *maskBits; + + FbStride dstStride, maskStride; + + int dstBpp, maskBpp; + + int dstXoff, dstYoff; + + int maskXoff, maskYoff; + + FbBits src; + + fbComposeGetSolid(pSrc, src, pDst->format); + + if ((src & 0xff000000) != 0xff000000) { + fbCompositeGeneral(op, pSrc, pMask, pDst, + xSrc, ySrc, xMask, yMask, xDst, yDst, width, height); + return; + } + fbGetStipDrawable(pMask->pDrawable, maskBits, maskStride, maskBpp, maskXoff, + maskYoff); + fbGetDrawable(pDst->pDrawable, dstBits, dstStride, dstBpp, dstXoff, + dstYoff); + + switch (dstBpp) { + case 32: + break; + case 24: + break; + case 16: + src = cvt8888to0565(src); + break; + } + + src = fbReplicatePixel(src, dstBpp); + + fbBltOne(maskBits + maskStride * (yMask + maskYoff), + maskStride, + xMask + maskXoff, + dstBits + dstStride * (yDst + dstYoff), + dstStride, + (xDst + dstXoff) * dstBpp, + dstBpp, width * dstBpp, height, 0x0, src, FB_ALLONES, 0x0); +} + +# define mod(a,b) ((b) == 1 ? 0 : (a) >= 0 ? (a) % (b) : (b) - (-a) % (b)) + +void +fbComposite(CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width, CARD16 height) +{ + RegionRec region; + + int n; + + BoxPtr pbox; + + CompositeFunc func = NULL; + + Bool srcRepeat = pSrc->pDrawable && pSrc->repeat; + + Bool maskRepeat = FALSE; + + Bool srcAlphaMap = pSrc->alphaMap != 0; + + Bool maskAlphaMap = FALSE; + + Bool dstAlphaMap = pDst->alphaMap != 0; + + int x_msk, y_msk, x_src, y_src, x_dst, y_dst; + + int w, h, w_this, h_this; + + + xDst += pDst->pDrawable->x; + yDst += pDst->pDrawable->y; + if (pSrc->pDrawable) { + xSrc += pSrc->pDrawable->x; + ySrc += pSrc->pDrawable->y; + } + if (pMask && pMask->pDrawable) { + xMask += pMask->pDrawable->x; + yMask += pMask->pDrawable->y; + maskRepeat = pMask->repeat == RepeatNormal; + maskAlphaMap = pMask->alphaMap != 0; + } + + if (pSrc->pDrawable && (!pMask || pMask->pDrawable) + && !pSrc->transform && !(pMask && pMask->transform) + && !maskAlphaMap && !srcAlphaMap && !dstAlphaMap + && (pSrc->filter != PictFilterConvolution) + && (!pMask || pMask->filter != PictFilterConvolution)) + switch (op) { + case PictOpSrc: + break; + case PictOpOver: + if (pMask) { + if (fbCanGetSolid(pSrc) && !maskRepeat) { + srcRepeat = FALSE; + if (PICT_FORMAT_COLOR(pSrc->format)) { + switch (pMask->format) { + case PICT_a8: + switch (pDst->format) { + case PICT_r5g6b5: + case PICT_b5g6r5: + func = fbCompositeSolidMask_nx8x0565; + break; + case PICT_r8g8b8: + case PICT_b8g8r8: + func = fbCompositeSolidMask_nx8x0888; + break; + case PICT_a8r8g8b8: + case PICT_x8r8g8b8: + case PICT_a8b8g8r8: + case PICT_x8b8g8r8: + func = fbCompositeSolidMask_nx8x8888; + break; + default: + break; + } + break; + case PICT_a8r8g8b8: + if (pMask->componentAlpha) { + switch (pDst->format) { + case PICT_a8r8g8b8: + case PICT_x8r8g8b8: + func = + fbCompositeSolidMask_nx8888x8888C; + break; + case PICT_r5g6b5: + func = + fbCompositeSolidMask_nx8888x0565C; + break; + default: + break; + } + } + break; + case PICT_a8b8g8r8: + if (pMask->componentAlpha) { + switch (pDst->format) { + case PICT_a8b8g8r8: + case PICT_x8b8g8r8: + func = + fbCompositeSolidMask_nx8888x8888C; + break; + case PICT_b5g6r5: + func = + fbCompositeSolidMask_nx8888x0565C; + break; + default: + break; + } + } + break; + case PICT_a1: + switch (pDst->format) { + case PICT_r5g6b5: + case PICT_b5g6r5: + case PICT_r8g8b8: + case PICT_b8g8r8: + case PICT_a8r8g8b8: + case PICT_x8r8g8b8: + case PICT_a8b8g8r8: + case PICT_x8b8g8r8: + func = fbCompositeSolidMask_nx1xn; + break; + default: + break; + } + break; + default: + break; + } + default: + break; + } + } + else if (!srcRepeat) { /* has mask and non-repeating source */ + if (pSrc->pDrawable == pMask->pDrawable && + xSrc == xMask && ySrc == yMask && + !pMask->componentAlpha && !maskRepeat) { + /* source == mask: non-premultiplied data */ + switch (pSrc->format) { + case PICT_x8b8g8r8: + switch (pMask->format) { + case PICT_a8r8g8b8: + case PICT_a8b8g8r8: + switch (pDst->format) { + case PICT_a8r8g8b8: + case PICT_x8r8g8b8: + break; + case PICT_r5g6b5: + break; + default: + break; + } + break; + default: + break; + } + break; + case PICT_x8r8g8b8: + switch (pMask->format) { + case PICT_a8r8g8b8: + case PICT_a8b8g8r8: + switch (pDst->format) { + case PICT_a8b8g8r8: + case PICT_x8b8g8r8: + break; + case PICT_r5g6b5: + break; + default: + break; + } + break; + default: + break; + } + break; + default: + break; + } + break; + } + else { + /* non-repeating source, repeating mask => translucent window */ + if (fbCanGetSolid(pMask)) { + if (pSrc->format == PICT_x8r8g8b8 && + pDst->format == PICT_x8r8g8b8 && + pMask->format == PICT_a8) { + } + } + } + } + } + else { /* no mask */ + + if (fbCanGetSolid(pSrc)) { + /* no mask and repeating source */ + switch (pSrc->format) { + case PICT_a8r8g8b8: + switch (pDst->format) { + case PICT_a8r8g8b8: + case PICT_x8r8g8b8: + break; + case PICT_r5g6b5: + break; + default: + break; + } + break; + default: + break; + } + } + else if (!srcRepeat) { + switch (pSrc->format) { + case PICT_a8r8g8b8: + switch (pDst->format) { + case PICT_a8r8g8b8: + case PICT_x8r8g8b8: + func = fbCompositeSrc_8888x8888; + break; + case PICT_r8g8b8: + func = fbCompositeSrc_8888x0888; + break; + case PICT_r5g6b5: + func = fbCompositeSrc_8888x0565; + break; + default: + break; + } + break; + case PICT_x8r8g8b8: + switch (pDst->format) { + case PICT_a8r8g8b8: + case PICT_x8r8g8b8: + break; + default: + break; + } + case PICT_x8b8g8r8: + switch (pDst->format) { + case PICT_a8b8g8r8: + case PICT_x8b8g8r8: + break; + default: + break; + } + break; + case PICT_a8b8g8r8: + switch (pDst->format) { + case PICT_a8b8g8r8: + case PICT_x8b8g8r8: + func = fbCompositeSrc_8888x8888; + break; + case PICT_b8g8r8: + func = fbCompositeSrc_8888x0888; + break; + case PICT_b5g6r5: + func = fbCompositeSrc_8888x0565; + break; + default: + break; + } + break; + case PICT_r5g6b5: + switch (pDst->format) { + case PICT_r5g6b5: + func = fbCompositeSrc_0565x0565; + break; + default: + break; + } + break; + case PICT_b5g6r5: + switch (pDst->format) { + case PICT_b5g6r5: + func = fbCompositeSrc_0565x0565; + break; + default: + break; + } + break; + default: + break; + } + } + } + break; + case PictOpAdd: + if (pMask == 0) { + switch (pSrc->format) { + case PICT_a8r8g8b8: + switch (pDst->format) { + case PICT_a8r8g8b8: + func = fbCompositeSrcAdd_8888x8888; + break; + default: + break; + } + break; + case PICT_a8b8g8r8: + switch (pDst->format) { + case PICT_a8b8g8r8: + func = fbCompositeSrcAdd_8888x8888; + break; + default: + break; + } + break; + case PICT_a8: + switch (pDst->format) { + case PICT_a8: + func = fbCompositeSrcAdd_8000x8000; + break; + default: + break; + } + break; + case PICT_a1: + switch (pDst->format) { + case PICT_a1: + func = fbCompositeSrcAdd_1000x1000; + break; + default: + break; + } + break; + default: + break; + } + } + break; + } + + if (!func) { + /* no fast path, use the general code */ + fbCompositeGeneral(op, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask, + xDst, yDst, width, height); + return; + } + + if (!miComputeCompositeRegion(®ion, + pSrc, + pMask, + pDst, + xSrc, + ySrc, + xMask, yMask, xDst, yDst, width, height)) + return; + + n = REGION_NUM_RECTS(®ion); + pbox = REGION_RECTS(®ion); + while (n--) { + h = pbox->y2 - pbox->y1; + y_src = pbox->y1 - yDst + ySrc; + y_msk = pbox->y1 - yDst + yMask; + y_dst = pbox->y1; + while (h) { + h_this = h; + w = pbox->x2 - pbox->x1; + x_src = pbox->x1 - xDst + xSrc; + x_msk = pbox->x1 - xDst + xMask; + x_dst = pbox->x1; + if (maskRepeat) { + y_msk = + mod(y_msk - pMask->pDrawable->y, pMask->pDrawable->height); + if (h_this > pMask->pDrawable->height - y_msk) + h_this = pMask->pDrawable->height - y_msk; + y_msk += pMask->pDrawable->y; + } + if (srcRepeat) { + y_src = + mod(y_src - pSrc->pDrawable->y, pSrc->pDrawable->height); + if (h_this > pSrc->pDrawable->height - y_src) + h_this = pSrc->pDrawable->height - y_src; + y_src += pSrc->pDrawable->y; + } + while (w) { + w_this = w; + if (maskRepeat) { + x_msk = + mod(x_msk - pMask->pDrawable->x, + pMask->pDrawable->width); + if (w_this > pMask->pDrawable->width - x_msk) + w_this = pMask->pDrawable->width - x_msk; + x_msk += pMask->pDrawable->x; + } + if (srcRepeat) { + x_src = + mod(x_src - pSrc->pDrawable->x, pSrc->pDrawable->width); + if (w_this > pSrc->pDrawable->width - x_src) + w_this = pSrc->pDrawable->width - x_src; + x_src += pSrc->pDrawable->x; + } + (*func) (op, pSrc, pMask, pDst, + x_src, y_src, x_msk, y_msk, x_dst, y_dst, + w_this, h_this); + w -= w_this; + x_src += w_this; + x_msk += w_this; + x_dst += w_this; + } + h -= h_this; + y_src += h_this; + y_msk += h_this; + y_dst += h_this; + } + pbox++; + } + REGION_UNINIT(®ion); +} + + +Bool +fbPictureInit(ScreenPtr pScreen, PictFormatPtr formats, int nformats) +{ + + + PictureScreenPtr ps; + + if (!miPictureInit(pScreen, formats, nformats)) + return FALSE; + ps = GetPictureScreen(pScreen); + ps->Composite = fbComposite; + ps->Glyphs = miGlyphs; + ps->CompositeRects = miCompositeRects; + ps->RasterizeTrapezoid = fbRasterizeTrapezoid; + ps->AddTraps = fbAddTraps; + ps->AddTriangles = fbAddTriangles; + + + return TRUE; +} + diff --git a/fb/fbpict.h b/fb/fbpict.h new file mode 100644 index 0000000..732c618 --- /dev/null +++ b/fb/fbpict.h @@ -0,0 +1,610 @@ +/* + * + * Copyright © 2000 Keith Packard, member of The XFree86 Project, 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, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#ifndef _FBPICT_H_ +#define _FBPICT_H_ + +#include "renderedge.h" + +#if defined(__GNUC__) +#define INLINE __inline__ +#else +#define INLINE +#endif + +#define FbIntMult(a,b,t) ( (t) = (a) * (b) + 0x80, ( ( ( (t)>>8 ) + (t) )>>8 ) ) +#define FbIntDiv(a,b) (((CARD16) (a) * 255) / (b)) + +#define FbGet8(v,i) ((CARD16) (CARD8) ((v) >> i)) + +/* + * There are two ways of handling alpha -- either as a single unified value or + * a separate value for each component, hence each macro must have two + * versions. The unified alpha version has a 'U' at the end of the name, + * the component version has a 'C'. Similarly, functions which deal with + * this difference will have two versions using the same convention. + */ + +#define FbOverU(x,y,i,a,t) ((t) = FbIntMult(FbGet8(y,i),(a),(t)) + FbGet8(x,i),\ + (CARD32) ((CARD8) ((t) | (0 - ((t) >> 8)))) << (i)) + +#define FbOverC(x,y,i,a,t) ((t) = FbIntMult(FbGet8(y,i),FbGet8(a,i),(t)) + FbGet8(x,i),\ + (CARD32) ((CARD8) ((t) | (0 - ((t) >> 8)))) << (i)) + +#define FbInU(x,i,a,t) ((CARD32) FbIntMult(FbGet8(x,i),(a),(t)) << (i)) + +#define FbInC(x,i,a,t) ((CARD32) FbIntMult(FbGet8(x,i),FbGet8(a,i),(t)) << (i)) + +#define FbGen(x,y,i,ax,ay,t,u,v) ((t) = (FbIntMult(FbGet8(y,i),ay,(u)) + \ + FbIntMult(FbGet8(x,i),ax,(v))),\ + (CARD32) ((CARD8) ((t) | \ + (0 - ((t) >> 8)))) << (i)) + +#define FbAdd(x,y,i,t) ((t) = FbGet8(x,i) + FbGet8(y,i), \ + (CARD32) ((CARD8) ((t) | (0 - ((t) >> 8)))) << (i)) + +#define Alpha(x) ((x) >> 24) +#define Red(x) (((x) >> 16) & 0xff) +#define Green(x) (((x) >> 8) & 0xff) +#define Blue(x) ((x) & 0xff) + +/** + * Returns TRUE if the fbComposeGetSolid can be used to get a single solid + * color representing every source sampling location of the picture. + */ +static INLINE Bool +fbCanGetSolid(PicturePtr pict) +{ + if (pict->pDrawable == NULL || + pict->pDrawable->width != 1 || pict->pDrawable->height != 1) { + return FALSE; + } + if (pict->repeat != RepeatNormal) + return FALSE; + + switch (pict->format) { + case PICT_a8r8g8b8: + case PICT_x8r8g8b8: + case PICT_a8b8g8r8: + case PICT_x8b8g8r8: + case PICT_r8g8b8: + case PICT_b8g8r8: + case PICT_r5g6b5: + case PICT_b5g6r5: + return TRUE; + default: + return FALSE; + } +} + +#define fbComposeGetSolid(pict, bits, fmt) { \ + FbBits *__bits__; \ + FbStride __stride__; \ + int __bpp__; \ + int __xoff__ _X_UNUSED,__yoff__ _X_UNUSED; \ +\ + fbGetDrawable((pict)->pDrawable,__bits__,__stride__,__bpp__,__xoff__,__yoff__); \ + switch (__bpp__) { \ + case 32: \ + (bits) = *(CARD32 *) __bits__; \ + break; \ + case 24: \ + (bits) = Fetch24 ((CARD8 *) __bits__); \ + break; \ + case 16: \ + (bits) = *(CARD16 *) __bits__; \ + (bits) = cvt0565to8888(bits); \ + break; \ + default: \ + return; \ + } \ + /* If necessary, convert RGB <--> BGR. */ \ + if (PICT_FORMAT_TYPE((pict)->format) != PICT_FORMAT_TYPE(fmt)) \ + { \ + (bits) = (((bits) & 0xff000000) | \ + (((bits) & 0x00ff0000) >> 16) | \ + (((bits) & 0x0000ff00) >> 0) | \ + (((bits) & 0x000000ff) << 16)); \ + } \ + /* manage missing src alpha */ \ + if ((pict)->pFormat->direct.alphaMask == 0) \ + (bits) |= 0xff000000; \ +} + +#define fbComposeGetStart(pict,x,y,type,stride,line,mul) {\ + FbBits *__bits__; \ + FbStride __stride__; \ + int __bpp__; \ + int __xoff__,__yoff__; \ +\ + fbGetDrawable((pict)->pDrawable,__bits__,__stride__,__bpp__,__xoff__,__yoff__); \ + (stride) = __stride__ * sizeof (FbBits) / sizeof (type); \ + (line) = ((type *) __bits__) + (stride) * ((y) + __yoff__) + (mul) * ((x) + __xoff__); \ +} +#define cvt8888to0565(s) ((((s) >> 3) & 0x001f) | \ + (((s) >> 5) & 0x07e0) | \ + (((s) >> 8) & 0xf800)) +#define cvt0565to8888(s) (((((s) << 3) & 0xf8) | (((s) >> 2) & 0x7)) | \ + ((((s) << 5) & 0xfc00) | (((s) >> 1) & 0x300)) | \ + ((((s) << 8) & 0xf80000) | (((s) << 3) & 0x70000))) + +#if IMAGE_BYTE_ORDER == MSBFirst +#define Fetch24(a) ((unsigned long) (a) & 1 ? \ + ((*(a) << 16) | *((CARD16 *) ((a)+1))) : \ + ((*((CARD16 *) (a)) << 8) | *((a)+2))) +#define Store24(a,v) ((unsigned long) (a) & 1 ? \ + ((*(a) = (CARD8) ((v) >> 16)), \ + (*((CARD16 *) ((a)+1)) = (CARD16) (v))) : \ + ((*((CARD16 *) (a)) = (CARD16) ((v) >> 8)), \ + (*((a)+2) = (CARD8) (v)))) +#else +#define Fetch24(a) ((unsigned long) (a) & 1 ? \ + ((*(a)) | (*((CARD16 *) ((a)+1)) << 8)) : \ + ((*((CARD16 *) (a))) | (*((a)+2) << 16))) +#define Store24(a,v) ((unsigned long) (a) & 1 ? \ + ((*(a) = (CARD8) (v)), \ + (*((CARD16 *) ((a)+1)) = (CARD16) ((v) >> 8))) : \ + ((*((CARD16 *) (a)) = (CARD16) (v)),\ + (*((a)+2) = (CARD8) ((v) >> 16)))) +#endif + +/* + The methods below use some tricks to be able to do two color + components at the same time. +*/ + +/* + x_c = (x_c * a) / 255 +*/ +#define FbByteMul(x, a) do { \ + CARD32 t = ((x & 0xff00ff) * a) + 0x800080; \ + t = (t + ((t >> 8) & 0xff00ff)) >> 8; \ + t &= 0xff00ff; \ + \ + x = (((x >> 8) & 0xff00ff) * a) + 0x800080; \ + x = (x + ((x >> 8) & 0xff00ff)); \ + x &= 0xff00ff00; \ + x += t; \ + } while (0) + +/* + x_c = (x_c * a) / 255 + y +*/ +#define FbByteMulAdd(x, a, y) do { \ + CARD32 t = ((x & 0xff00ff) * a) + 0x800080; \ + t = (t + ((t >> 8) & 0xff00ff)) >> 8; \ + t &= 0xff00ff; \ + t += y & 0xff00ff; \ + t |= 0x1000100 - ((t >> 8) & 0xff00ff); \ + t &= 0xff00ff; \ + \ + x = (((x >> 8) & 0xff00ff) * a) + 0x800080; \ + x = (x + ((x >> 8) & 0xff00ff)) >> 8; \ + x &= 0xff00ff; \ + x += (y >> 8) & 0xff00ff; \ + x |= 0x1000100 - ((x >> 8) & 0xff00ff); \ + x &= 0xff00ff; \ + x <<= 8; \ + x += t; \ + } while (0) + +/* + x_c = (x_c * a + y_c * b) / 255 +*/ +#define FbByteAddMul(x, a, y, b) do { \ + CARD32 t; \ + CARD32 r = (x >> 24) * a + (y >> 24) * b + 0x80; \ + r += (r >> 8); \ + r >>= 8; \ + \ + t = (x & 0xff00) * a + (y & 0xff00) * b; \ + t += (t >> 8) + 0x8000; \ + t >>= 16; \ + \ + t |= r << 16; \ + t |= 0x1000100 - ((t >> 8) & 0xff00ff); \ + t &= 0xff00ff; \ + t <<= 8; \ + \ + r = ((x >> 16) & 0xff) * a + ((y >> 16) & 0xff) * b + 0x80; \ + r += (r >> 8); \ + r >>= 8; \ + \ + x = (x & 0xff) * a + (y & 0xff) * b + 0x80; \ + x += (x >> 8); \ + x >>= 8; \ + x |= r << 16; \ + x |= 0x1000100 - ((x >> 8) & 0xff00ff); \ + x &= 0xff00ff; \ + x |= t; \ +} while (0) + +/* + x_c = (x_c * a + y_c *b) / 256 +*/ +#define FbByteAddMul_256(x, a, y, b) do { \ + CARD32 t = (x & 0xff00ff) * a + (y & 0xff00ff) * b; \ + t >>= 8; \ + t &= 0xff00ff; \ + \ + x = ((x >> 8) & 0xff00ff) * a + ((y >> 8) & 0xff00ff) * b; \ + x &= 0xff00ff00; \ + x += t; \ +} while (0) +/* + x_c = (x_c * a_c) / 255 +*/ +#define FbByteMulC(x, a) do { \ + CARD32 t; \ + CARD32 r = (x & 0xff) * (a & 0xff); \ + r |= (x & 0xff0000) * ((a >> 16) & 0xff); \ + r += 0x800080; \ + r = (r + ((r >> 8) & 0xff00ff)) >> 8; \ + r &= 0xff00ff; \ + \ + x >>= 8; \ + t = (x & 0xff) * ((a >> 8) & 0xff); \ + t |= (x & 0xff0000) * (a >> 24); \ + t += 0x800080; \ + t = t + ((t >> 8) & 0xff00ff); \ + x = r | (t & 0xff00ff00); \ + \ + } while (0) + +/* + x_c = (x_c * a) / 255 + y +*/ +#define FbByteMulAddC(x, a, y) do { \ + CARD32 t; \ + CARD32 r = (x & 0xff) * (a & 0xff); \ + r |= (x & 0xff0000) * ((a >> 16) & 0xff); \ + r += 0x800080; \ + r = (r + ((r >> 8) & 0xff00ff)) >> 8; \ + r &= 0xff00ff; \ + r += y & 0xff00ff; \ + r |= 0x1000100 - ((r >> 8) & 0xff00ff); \ + r &= 0xff00ff; \ + \ + x >>= 8; \ + t = (x & 0xff) * ((a >> 8) & 0xff); \ + t |= (x & 0xff0000) * (a >> 24); \ + t += 0x800080; \ + t = (t + ((t >> 8) & 0xff00ff)) >> 8; \ + t &= 0xff00ff; \ + t += (y >> 8) & 0xff00ff; \ + t |= 0x1000100 - ((t >> 8) & 0xff00ff); \ + t &= 0xff00ff; \ + x = r | (t << 8); \ + } while (0) + +/* + x_c = (x_c * a_c + y_c * b) / 255 +*/ +#define FbByteAddMulC(x, a, y, b) do { \ + CARD32 t; \ + CARD32 r = (x >> 24) * (a >> 24) + (y >> 24) * b; \ + r += (r >> 8) + 0x80; \ + r >>= 8; \ + \ + t = (x & 0xff00) * ((a >> 8) & 0xff) + (y & 0xff00) * b; \ + t += (t >> 8) + 0x8000; \ + t >>= 16; \ + \ + t |= r << 16; \ + t |= 0x1000100 - ((t >> 8) & 0xff00ff); \ + t &= 0xff00ff; \ + t <<= 8; \ + \ + r = ((x >> 16) & 0xff) * ((a >> 16) & 0xff) + ((y >> 16) & 0xff) * b + 0x80; \ + r += (r >> 8); \ + r >>= 8; \ + \ + x = (x & 0xff) * (a & 0xff) + (y & 0xff) * b + 0x80; \ + x += (x >> 8); \ + x >>= 8; \ + x |= r << 16; \ + x |= 0x1000100 - ((x >> 8) & 0xff00ff); \ + x &= 0xff00ff; \ + x |= t; \ + } while (0) + +/* + x_c = min(x_c + y_c, 255) +*/ +#define FbByteAdd(x, y) do { \ + CARD32 t; \ + CARD32 r = (x & 0xff00ff) + (y & 0xff00ff); \ + r |= 0x1000100 - ((r >> 8) & 0xff00ff); \ + r &= 0xff00ff; \ + \ + t = ((x >> 8) & 0xff00ff) + ((y >> 8) & 0xff00ff); \ + t |= 0x1000100 - ((t >> 8) & 0xff00ff); \ + r |= (t & 0xff00ff) << 8; \ + x = r; \ + } while (0) + +#define div_255(x) (((x) + 0x80 + (((x) + 0x80) >> 8)) >> 8) + +#if defined(__i386__) && defined(__GNUC__) +#define FASTCALL __attribute__((regparm(3))) +#else +#define FASTCALL +#endif + +typedef struct _FbComposeData { + CARD8 op; + PicturePtr src; + PicturePtr mask; + PicturePtr dest; + INT16 xSrc; + INT16 ySrc; + INT16 xMask; + INT16 yMask; + INT16 xDest; + INT16 yDest; + CARD16 width; + CARD16 height; +} FbComposeData; + +typedef FASTCALL void (*CombineMaskU) (CARD32 *src, const CARD32 *mask, + int width); +typedef FASTCALL void (*CombineFuncU) (CARD32 *dest, const CARD32 *src, + int width); +typedef FASTCALL void (*CombineFuncC) (CARD32 *dest, CARD32 *src, CARD32 *mask, + int width); + +typedef struct _FbComposeFunctions { + const CombineFuncU *combineU; + const CombineFuncC *combineC; + CombineMaskU combineMaskU; +} FbComposeFunctions; + +/* fbcompose.c */ + +void + +fbCompositeGeneral(CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, INT16 yDst, CARD16 width, CARD16 height); + +/* fbedge.c */ +void + +fbRasterizeEdges(FbBits * buf, + int bpp, + int width, + int stride, + RenderEdge * l, RenderEdge * r, xFixed t, xFixed b); + +/* fbpict.c */ +CARD32 + fbOver(CARD32 x, CARD32 y); + +CARD32 + fbOver24(CARD32 x, CARD32 y); + +CARD32 + fbIn(CARD32 x, CARD8 y); + +void + +fbCompositeSolidMask_nx8x8888(CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, CARD16 width, CARD16 height); + +void + +fbCompositeSolidMask_nx8x0888(CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, CARD16 width, CARD16 height); + +void + +fbCompositeSolidMask_nx8888x8888C(CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, CARD16 width, CARD16 height); + +void + +fbCompositeSolidMask_nx8x0565(CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, CARD16 width, CARD16 height); + +void + +fbCompositeSolidMask_nx8888x0565C(CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, CARD16 width, CARD16 height); + +void + +fbCompositeSrc_8888x8888(CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, INT16 yDst, CARD16 width, CARD16 height); + +void + +fbCompositeSrc_8888x0888(CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, INT16 yDst, CARD16 width, CARD16 height); + +void + +fbCompositeSrc_8888x0565(CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, INT16 yDst, CARD16 width, CARD16 height); + +void + +fbCompositeSrc_0565x0565(CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, INT16 yDst, CARD16 width, CARD16 height); + +void + +fbCompositeSrcAdd_8000x8000(CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, CARD16 width, CARD16 height); + +void + +fbCompositeSrcAdd_8888x8888(CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, CARD16 width, CARD16 height); + +void + +fbCompositeSrcAdd_1000x1000(CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, CARD16 width, CARD16 height); + +void + +fbCompositeSolidMask_nx1xn(CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, INT16 yDst, CARD16 width, CARD16 height); + +void + +fbComposite(CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width, CARD16 height); + +/* fbtrap.c */ + +void + +fbAddTraps(PicturePtr pPicture, + INT16 xOff, INT16 yOff, int ntrap, xTrap * traps); + +void + +fbRasterizeTrapezoid(PicturePtr alpha, xTrapezoid * trap, int x_off, int y_off); + +void + +fbAddTriangles(PicturePtr pPicture, + INT16 xOff, INT16 yOff, int ntri, xTriangle * tris); + +#endif /* _FBPICT_H_ */ diff --git a/fb/fbpixmap.c b/fb/fbpixmap.c new file mode 100644 index 0000000..f047ed4 --- /dev/null +++ b/fb/fbpixmap.c @@ -0,0 +1,365 @@ +/* + * + * Copyright © 1998 Keith Packard + * + * 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, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include + +#include "fb.h" + +PixmapPtr +fbCreatePixmapBpp(ScreenPtr pScreen, int width, int height, int depth, int bpp) +{ + PixmapPtr pPixmap; + + size_t datasize; + + size_t paddedWidth; + + int adjust; + + int base; + + paddedWidth = ((width * bpp + FB_MASK) >> FB_SHIFT) * sizeof(FbBits); + if (paddedWidth / 4 > 32767 || height > 32767) + return NullPixmap; + datasize = height * paddedWidth; + base = pScreen->totalPixmapSize; + adjust = 0; + if (base & 7) + adjust = 8 - (base & 7); + datasize += adjust; +#ifdef FB_DEBUG + datasize += 2 * paddedWidth; +#endif + pPixmap = AllocatePixmap(pScreen, datasize); + if (!pPixmap) + return NullPixmap; + pPixmap->drawable.type = DRAWABLE_PIXMAP; + pPixmap->drawable.class = 0; + pPixmap->drawable.pScreen = pScreen; + pPixmap->drawable.depth = depth; + pPixmap->drawable.bitsPerPixel = bpp; + pPixmap->drawable.id = 0; + pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER; + pPixmap->drawable.x = 0; + pPixmap->drawable.y = 0; + pPixmap->drawable.width = width; + pPixmap->drawable.height = height; + pPixmap->devKind = paddedWidth; + pPixmap->refcnt = 1; + pPixmap->devPrivate.ptr = (pointer) ((char *) pPixmap + base + adjust); +#ifdef FB_DEBUG + pPixmap->devPrivate.ptr = + (void *) ((char *) pPixmap->devPrivate.ptr + paddedWidth); + fbInitializeDrawable(&pPixmap->drawable); +#endif + + + return pPixmap; +} + +PixmapPtr +fbCreatePixmap(ScreenPtr pScreen, int width, int height, int depth) +{ + int bpp; + + bpp = BitsPerPixel(depth); + if (bpp == 32 && depth <= 24) + bpp = fbGetScreenPrivate(pScreen)->pix32bpp; + return fbCreatePixmapBpp(pScreen, width, height, depth, bpp); +} + +Bool +fbDestroyPixmap(PixmapPtr pPixmap) +{ + if (--pPixmap->refcnt) + return TRUE; + free(pPixmap); + return TRUE; +} + +#define ADDRECT(reg,r,fr,rx1,ry1,rx2,ry2) \ +if (((rx1) < (rx2)) && ((ry1) < (ry2)) && \ + (!((reg)->data->numRects && \ + ((r-1)->y1 == (ry1)) && \ + ((r-1)->y2 == (ry2)) && \ + ((r-1)->x1 <= (rx1)) && \ + ((r-1)->x2 >= (rx2))))) \ +{ \ + if ((reg)->data->numRects == (reg)->data->size) \ + { \ + miRectAlloc(reg, 1); \ + fr = REGION_BOXPTR(reg); \ + r = fr + (reg)->data->numRects; \ + } \ + r->x1 = (rx1); \ + r->y1 = (ry1); \ + r->x2 = (rx2); \ + r->y2 = (ry2); \ + (reg)->data->numRects++; \ + if(r->x1 < (reg)->extents.x1) \ + (reg)->extents.x1 = r->x1; \ + if(r->x2 > (reg)->extents.x2) \ + (reg)->extents.x2 = r->x2; \ + r++; \ +} + +/* Convert bitmap clip mask into clipping region. + * First, goes through each line and makes boxes by noting the transitions + * from 0 to 1 and 1 to 0. + * Then it coalesces the current line with the previous if they have boxes + * at the same X coordinates. + */ +RegionPtr +fbPixmapToRegion(PixmapPtr pPix) +{ + RegionPtr pReg; + + FbBits *pw, w; + + int ib; + + int width, h, base, rx1 = 0, crects; + + FbBits *pwLineEnd; + + int irectPrevStart, irectLineStart; + + BoxPtr prectO, prectN; + + BoxPtr FirstRect, rects, prectLineStart; + + Bool fInBox, fSame; + + FbBits mask0 = FB_ALLONES & ~FbScrRight(FB_ALLONES, 1); + + FbBits *pwLine; + + int nWidth; + + pReg = REGION_CREATE(NULL, 1); + if (!pReg) + return NullRegion; + FirstRect = REGION_BOXPTR(pReg); + rects = FirstRect; + + pwLine = (FbBits *) pPix->devPrivate.ptr; + nWidth = pPix->devKind >> (FB_SHIFT - 3); + + width = pPix->drawable.width; + pReg->extents.x1 = width - 1; + pReg->extents.x2 = 0; + irectPrevStart = -1; + for (h = 0; h < pPix->drawable.height; h++) { + pw = pwLine; + pwLine += nWidth; + irectLineStart = rects - FirstRect; + /* If the Screen left most bit of the word is set, we're starting in + * a box */ + if (*pw & mask0) { + fInBox = TRUE; + rx1 = 0; + } + else + fInBox = FALSE; + /* Process all words which are fully in the pixmap */ + pwLineEnd = pw + (width >> FB_SHIFT); + for (base = 0; pw < pwLineEnd; base += FB_UNIT) { + w = *pw++; + if (fInBox) { + if (!~w) + continue; + } + else { + if (!w) + continue; + } + for (ib = 0; ib < FB_UNIT; ib++) { + /* If the Screen left most bit of the word is set, we're + * starting a box */ + if (w & mask0) { + if (!fInBox) { + rx1 = base + ib; + /* start new box */ + fInBox = TRUE; + } + } + else { + if (fInBox) { + /* end box */ + ADDRECT(pReg, rects, FirstRect, + rx1, h, base + ib, h + 1); + fInBox = FALSE; + } + } + /* Shift the word VISUALLY left one. */ + w = FbScrLeft(w, 1); + } + } + if (width & FB_MASK) { + /* Process final partial word on line */ + w = *pw++; + for (ib = 0; ib < (width & FB_MASK); ib++) { + /* If the Screen left most bit of the word is set, we're + * starting a box */ + if (w & mask0) { + if (!fInBox) { + rx1 = base + ib; + /* start new box */ + fInBox = TRUE; + } + } + else { + if (fInBox) { + /* end box */ + ADDRECT(pReg, rects, FirstRect, + rx1, h, base + ib, h + 1); + fInBox = FALSE; + } + } + /* Shift the word VISUALLY left one. */ + w = FbScrLeft(w, 1); + } + } + /* If scanline ended with last bit set, end the box */ + if (fInBox) { + ADDRECT(pReg, rects, FirstRect, + rx1, h, base + (width & FB_MASK), h + 1); + } + /* if all rectangles on this line have the same x-coords as + * those on the previous line, then add 1 to all the previous y2s and + * throw away all the rectangles from this line + */ + fSame = FALSE; + if (irectPrevStart != -1) { + crects = irectLineStart - irectPrevStart; + if (crects == ((rects - FirstRect) - irectLineStart)) { + prectO = FirstRect + irectPrevStart; + prectN = prectLineStart = FirstRect + irectLineStart; + fSame = TRUE; + while (prectO < prectLineStart) { + if ((prectO->x1 != prectN->x1) || + (prectO->x2 != prectN->x2)) { + fSame = FALSE; + break; + } + prectO++; + prectN++; + } + if (fSame) { + prectO = FirstRect + irectPrevStart; + while (prectO < prectLineStart) { + prectO->y2 += 1; + prectO++; + } + rects -= crects; + pReg->data->numRects -= crects; + } + } + } + if (!fSame) + irectPrevStart = irectLineStart; + } + if (!pReg->data->numRects) + pReg->extents.x1 = pReg->extents.x2 = 0; + else { + pReg->extents.y1 = REGION_BOXPTR(pReg)->y1; + pReg->extents.y2 = REGION_END(pReg)->y2; + if (pReg->data->numRects == 1) { + free(pReg->data); + pReg->data = (RegDataPtr) NULL; + } + } +#ifdef DEBUG + if (!miValidRegion(pReg)) + FatalError("Assertion failed file %s, line %d: expr\n", __FILE__, + __LINE__); +#endif + return (pReg); +} + +#ifdef FB_DEBUG + +#include + +static Bool +fbValidateBits(FbStip * bits, int stride, FbStip data) +{ + while (stride--) { + if (*bits != data) { + fprintf(stderr, "fbValidateBits failed\n"); + return FALSE; + } + bits++; + } +} + +void +fbValidateDrawable(DrawablePtr pDrawable) +{ + FbStip *bits, *first, *last; + + int stride, bpp; + + int xoff, yoff; + + int height; + + Bool failed; + + if (pDrawable->type != DRAWABLE_PIXMAP) + pDrawable = (DrawablePtr) fbGetWindowPixmap(pDrawable); + fbGetStipDrawable(pDrawable, bits, stride, bpp, xoff, yoff); + first = bits - stride; + last = bits + stride * pDrawable->height; + if (!fbValidateBits(first, stride, FB_HEAD_BITS) || + !fbValidateBits(last, stride, FB_TAIL_BITS)) + fbInitializeDrawable(pDrawable); +} + +void +fbSetBits(FbStip * bits, int stride, FbStip data) +{ + while (stride--) + *bits++ = data; +} + +void +fbInitializeDrawable(DrawablePtr pDrawable) +{ + FbStip *bits, *first, *last; + + int stride, bpp; + + int xoff, yoff; + + fbGetStipDrawable(pDrawable, bits, stride, bpp, xoff, yoff); + first = bits - stride; + last = bits + stride * pDrawable->height; + fbSetBits(first, stride, FB_HEAD_BITS); + fbSetBits(last, stride, FB_TAIL_BITS); +} +#endif /* FB_DEBUG */ diff --git a/fb/fbpoint.c b/fb/fbpoint.c new file mode 100644 index 0000000..986b383 --- /dev/null +++ b/fb/fbpoint.c @@ -0,0 +1,165 @@ +/* + * + * Copyright © 1998 Keith Packard + * + * 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, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "fb.h" + +typedef void (*FbDots) (FbBits * dst, + FbStride dstStride, + int dstBpp, + BoxPtr pBox, + xPoint * pts, + int npt, + int xorg, + int yorg, int xoff, int yoff, FbBits and, FbBits xor); + +void +fbDots(FbBits * dstOrig, + FbStride dstStride, + int dstBpp, + BoxPtr pBox, + xPoint * pts, + int npt, + int xorg, int yorg, int xoff, int yoff, FbBits andOrig, FbBits xorOrig) +{ + FbStip *dst = (FbStip *) dstOrig; + + int x1, y1, x2, y2; + + int x, y; + + FbStip *d; + + FbStip and = andOrig; + + FbStip xor = xorOrig; + + dstStride = FbBitsStrideToStipStride(dstStride); + x1 = pBox->x1; + y1 = pBox->y1; + x2 = pBox->x2; + y2 = pBox->y2; + while (npt--) { + x = pts->x + xorg; + y = pts->y + yorg; + pts++; + if (x1 <= x && x < x2 && y1 <= y && y < y2) { + x = (x + xoff) * dstBpp; + d = dst + ((y + yoff) * dstStride) + (x >> FB_STIP_SHIFT); + x &= FB_STIP_MASK; + if (dstBpp == 24) { + FbStip leftMask, rightMask; + + int n, rot; + + FbStip andT, xorT; + + rot = FbFirst24Rot(x); + andT = FbRot24Stip(and, rot); + xorT = FbRot24Stip(xor, rot); + FbMaskStip(x, 24, leftMask, n, rightMask); + if (leftMask) { + *d = FbDoMaskRRop(*d, andT, xorT, leftMask); + andT = FbNext24Stip(andT); + xorT = FbNext24Stip(xorT); + d++; + } + if (rightMask) + *d = FbDoMaskRRop(*d, andT, xorT, rightMask); + } + else + { + FbStip mask; + + mask = FbStipMask(x, dstBpp); + *d = FbDoMaskRRop(*d, and, xor, mask); + } + } + } +} + +void +fbPolyPoint(DrawablePtr pDrawable, + GCPtr pGC, int mode, int nptInit, xPoint * pptInit) +{ + FbGCPrivPtr pPriv = fbGetGCPrivate(pGC); + + RegionPtr pClip = fbGetCompositeClip(pGC); + + FbBits *dst; + + FbStride dstStride; + + int dstBpp; + + int dstXoff, dstYoff; + + FbDots dots; + + FbBits and, xor; + + xPoint *ppt; + + int npt; + + BoxPtr pBox; + + int nBox; + + /* make pointlist origin relative */ + ppt = pptInit; + npt = nptInit; + if (mode == CoordModePrevious) { + npt--; + while (npt--) { + ppt++; + ppt->x += (ppt - 1)->x; + ppt->y += (ppt - 1)->y; + } + } + fbGetDrawable(pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); + and = pPriv->and; + xor = pPriv->xor; + dots = fbDots; + switch (dstBpp) { + case 8: + dots = fbDots8; + break; + case 16: + dots = fbDots16; + break; + case 24: + dots = fbDots24; + break; + case 32: + dots = fbDots32; + break; + } + for (nBox = REGION_NUM_RECTS(pClip), pBox = REGION_RECTS(pClip); + nBox--; pBox++) + (*dots) (dst, dstStride, dstBpp, pBox, pptInit, nptInit, + pDrawable->x, pDrawable->y, dstXoff, dstYoff, and, xor); +} diff --git a/fb/fbpush.c b/fb/fbpush.c new file mode 100644 index 0000000..e1a3f73 --- /dev/null +++ b/fb/fbpush.c @@ -0,0 +1,202 @@ +/* + * + * Copyright © 1998 Keith Packard + * + * 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, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "fb.h" + +void +fbPushPattern(DrawablePtr pDrawable, + GCPtr pGC, + FbStip * src, + FbStride srcStride, int srcX, int x, int y, int width, int height) +{ + FbStip *s, bitsMask, bitsMask0, bits; + + int xspan; + + int w; + + int lenspan; + + src += srcX >> FB_STIP_SHIFT; + srcX &= FB_STIP_MASK; + + bitsMask0 = FbStipMask(srcX, 1); + + while (height--) { + bitsMask = bitsMask0; + w = width; + s = src; + src += srcStride; + bits = *s++; + xspan = x; + while (w) { + if (bits & bitsMask) { + lenspan = 0; + do { + lenspan++; + if (lenspan == w) + break; + bitsMask = FbStipRight(bitsMask, 1); + if (!bitsMask) { + bits = *s++; + bitsMask = FbBitsMask(0, 1); + } + } while (bits & bitsMask); + fbFill(pDrawable, pGC, xspan, y, lenspan, 1); + xspan += lenspan; + w -= lenspan; + } + else { + do { + w--; + xspan++; + if (!w) + break; + bitsMask = FbStipRight(bitsMask, 1); + if (!bitsMask) { + bits = *s++; + bitsMask = FbBitsMask(0, 1); + } + } while (!(bits & bitsMask)); + } + } + y++; + } +} + +void +fbPushFill(DrawablePtr pDrawable, + GCPtr pGC, + FbStip * src, + FbStride srcStride, int srcX, int x, int y, int width, int height) +{ + FbGCPrivPtr pPriv = fbGetGCPrivate(pGC); + + if (pGC->fillStyle == FillSolid) { + FbBits *dst; + + FbStride dstStride; + + int dstBpp; + + int dstXoff, dstYoff; + + int dstX; + + int dstWidth; + + fbGetDrawable(pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); + dst = dst + (y + dstYoff) * dstStride; + dstX = (x + dstXoff) * dstBpp; + dstWidth = width * dstBpp; + if (dstBpp == 1) { + fbBltStip(src, + srcStride, + srcX, + (FbStip *) dst, + FbBitsStrideToStipStride(dstStride), + dstX, + dstWidth, + height, + FbStipple1Rop(pGC->alu, pGC->fgPixel), pPriv->pm, dstBpp); + } + else { + fbBltOne(src, + srcStride, + srcX, + dst, + dstStride, + dstX, + dstBpp, + dstWidth, + height, + pPriv->and, pPriv->xor, + fbAnd(GXnoop, (FbBits) 0, FB_ALLONES), + fbXor(GXnoop, (FbBits) 0, FB_ALLONES)); + } + } + else { + fbPushPattern(pDrawable, pGC, src, srcStride, srcX, + x, y, width, height); + } +} + +void +fbPushImage(DrawablePtr pDrawable, + GCPtr pGC, + FbStip * src, + FbStride srcStride, int srcX, int x, int y, int width, int height) +{ + RegionPtr pClip = fbGetCompositeClip(pGC); + + int nbox; + + BoxPtr pbox; + + int x1, y1, x2, y2; + + for (nbox = REGION_NUM_RECTS(pClip), + pbox = REGION_RECTS(pClip); nbox--; pbox++) { + x1 = x; + y1 = y; + x2 = x + width; + y2 = y + height; + if (x1 < pbox->x1) + x1 = pbox->x1; + if (y1 < pbox->y1) + y1 = pbox->y1; + if (x2 > pbox->x2) + x2 = pbox->x2; + if (y2 > pbox->y2) + y2 = pbox->y2; + if (x1 >= x2 || y1 >= y2) + continue; + fbPushFill(pDrawable, + pGC, + src + (y1 - y) * srcStride, + srcStride, srcX + (x1 - x), x1, y1, x2 - x1, y2 - y1); + } +} + +void +fbPushPixels(GCPtr pGC, + PixmapPtr pBitmap, + DrawablePtr pDrawable, int dx, int dy, int xOrg, int yOrg) +{ + FbStip *stip; + + FbStride stipStride; + + int stipBpp; + + int stipXoff _X_UNUSED, stipYoff _X_UNUSED; /* Assumed to be zero */ + + fbGetStipDrawable(&pBitmap->drawable, stip, stipStride, stipBpp, stipXoff, + stipYoff); + + fbPushImage(pDrawable, pGC, stip, stipStride, 0, xOrg, yOrg, dx, dy); +} diff --git a/fb/fbrop.h b/fb/fbrop.h new file mode 100644 index 0000000..4375411 --- /dev/null +++ b/fb/fbrop.h @@ -0,0 +1,137 @@ +/* + * Copyright © 1998 Keith Packard + * + * 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, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _FBROP_H_ +#define _FBROP_H_ + +typedef struct _mergeRopBits { + FbBits ca1, cx1, ca2, cx2; +} FbMergeRopRec, *FbMergeRopPtr; + +extern _X_EXPORT const FbMergeRopRec FbMergeRopBits[16]; + +#define FbDeclareMergeRop() FbBits _ca1, _cx1, _ca2, _cx2; +#define FbDeclarePrebuiltMergeRop() FbBits _cca, _ccx; + +#define FbInitializeMergeRop(alu,pm) {\ + const FbMergeRopRec *_bits; \ + _bits = &FbMergeRopBits[alu]; \ + _ca1 = _bits->ca1 & pm; \ + _cx1 = _bits->cx1 | ~pm; \ + _ca2 = _bits->ca2 & pm; \ + _cx2 = _bits->cx2 & pm; \ +} + +#define FbDestInvarientRop(alu,pm) ((pm) == FB_ALLONES && \ + (((alu) >> 1 & 5) == ((alu) & 5))) + +#define FbDestInvarientMergeRop() (_ca1 == 0 && _cx1 == 0) + +/* AND has higher precedence than XOR */ + +#define FbDoMergeRop(src, dst) \ + (((dst) & (((src) & _ca1) ^ _cx1)) ^ (((src) & _ca2) ^ _cx2)) + +#define FbDoDestInvarientMergeRop(src) (((src) & _ca2) ^ _cx2) + +#define FbDoMaskMergeRop(src, dst, mask) \ + (((dst) & ((((src) & _ca1) ^ _cx1) | ~(mask))) ^ ((((src) & _ca2) ^ _cx2) & (mask))) + +#define FbDoLeftMaskByteMergeRop(dst, src, lb, l) { \ + FbBits __xor = ((src) & _ca2) ^ _cx2; \ + FbDoLeftMaskByteRRop(dst,lb,l,((src) & _ca1) ^ _cx1,__xor); \ +} + +#define FbDoRightMaskByteMergeRop(dst, src, rb, r) { \ + FbBits __xor = ((src) & _ca2) ^ _cx2; \ + FbDoRightMaskByteRRop(dst,rb,r,((src) & _ca1) ^ _cx1,__xor); \ +} + +#define FbDoRRop(dst, and, xor) (((dst) & (and)) ^ (xor)) + +#define FbDoMaskRRop(dst, and, xor, mask) \ + (((dst) & ((and) | ~(mask))) ^ (xor & mask)) + +/* + * Take a single bit (0 or 1) and generate a full mask + */ +#define fbFillFromBit(b,t) (~((t) ((b) & 1)-1)) + +#define fbXorT(rop,fg,pm,t) ((((fg) & fbFillFromBit((rop) >> 1,t)) | \ + (~(fg) & fbFillFromBit((rop) >> 3,t))) & (pm)) + +#define fbAndT(rop,fg,pm,t) ((((fg) & fbFillFromBit (rop ^ (rop>>1),t)) | \ + (~(fg) & fbFillFromBit((rop>>2) ^ (rop>>3),t))) | \ + ~(pm)) + +#define fbXor(rop,fg,pm) fbXorT(rop,fg,pm,FbBits) + +#define fbAnd(rop,fg,pm) fbAndT(rop,fg,pm,FbBits) + +#define fbXorStip(rop,fg,pm) fbXorT(rop,fg,pm,FbStip) + +#define fbAndStip(rop,fg,pm) fbAndT(rop,fg,pm,FbStip) + +/* + * Stippling operations; + */ + +extern _X_EXPORT const FbBits fbStipple16Bits[256]; /* half of table */ + +#define FbStipple16Bits(b) \ + (fbStipple16Bits[(b)&0xff] | fbStipple16Bits[(b) >> 8] << FB_HALFUNIT) +extern _X_EXPORT const FbBits fbStipple8Bits[256]; +extern _X_EXPORT const FbBits fbStipple4Bits[16]; +extern _X_EXPORT const FbBits fbStipple2Bits[4]; +extern _X_EXPORT const FbBits fbStipple1Bits[2]; +extern _X_EXPORT const FbBits *const fbStippleTable[]; + +#define FbStippleRRop(dst, b, fa, fx, ba, bx) \ + (FbDoRRop(dst, fa, fx) & b) | (FbDoRRop(dst, ba, bx) & ~b) + +#define FbStippleRRopMask(dst, b, fa, fx, ba, bx, m) \ + (FbDoMaskRRop(dst, fa, fx, m) & (b)) | (FbDoMaskRRop(dst, ba, bx, m) & ~(b)) + +#define FbDoLeftMaskByteStippleRRop(dst, b, fa, fx, ba, bx, lb, l) { \ + FbBits __xor = ((fx) & (b)) | ((bx) & ~(b)); \ + FbDoLeftMaskByteRRop(dst, lb, l, ((fa) & (b)) | ((ba) & ~(b)), __xor); \ +} + +#define FbDoRightMaskByteStippleRRop(dst, b, fa, fx, ba, bx, rb, r) { \ + FbBits __xor = ((fx) & (b)) | ((bx) & ~(b)); \ + FbDoRightMaskByteRRop(dst, rb, r, ((fa) & (b)) | ((ba) & ~(b)), __xor); \ +} + +#define FbOpaqueStipple(b, fg, bg) (((fg) & (b)) | ((bg) & ~(b))) + +/* + * Compute rop for using tile code for 1-bit dest stipples; modifies + * existing rop to flip depending on pixel values + */ +#define FbStipple1RopPick(alu,b) (((alu) >> (2 - (((b) & 1) << 1))) & 3) + +#define FbOpaqueStipple1Rop(alu,fg,bg) (FbStipple1RopPick(alu,fg) | \ + (FbStipple1RopPick(alu,bg) << 2)) + +#define FbStipple1Rop(alu,fg) (FbStipple1RopPick(alu,fg) | 4) + +#endif diff --git a/fb/fbscreen.c b/fb/fbscreen.c new file mode 100644 index 0000000..cd99260 --- /dev/null +++ b/fb/fbscreen.c @@ -0,0 +1,214 @@ +/* + * Copyright © 1998 Keith Packard + * + * 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, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "fb.h" + +Bool +fbCloseScreen(int index, ScreenPtr pScreen) +{ + int d; + + DepthPtr depths = pScreen->allowedDepths; + + for (d = 0; d < pScreen->numDepths; d++) + free(depths[d].vids); + free(depths); + free(pScreen->visuals); + free(pScreen->devPrivate); + free(pScreen->devPrivates[fbScreenPrivateIndex].ptr); + return TRUE; +} + +Bool +fbRealizeFont(ScreenPtr pScreen, FontPtr pFont) +{ + return (TRUE); +} + +Bool +fbUnrealizeFont(ScreenPtr pScreen, FontPtr pFont) +{ + return (TRUE); +} + +void +fbQueryBestSize(int class, + unsigned short *width, unsigned short *height, + ScreenPtr pScreen) +{ + unsigned short w; + + switch (class) { + case CursorShape: + if (*width > pScreen->width) + *width = pScreen->width; + if (*height > pScreen->height) + *height = pScreen->height; + break; + case TileShape: + case StippleShape: + w = *width; + if ((w & (w - 1)) && w < FB_UNIT) { + for (w = 1; w < *width; w <<= 1); + *width = w; + } + } +} + +PixmapPtr +_fbGetWindowPixmap(WindowPtr pWindow) +{ + return fbGetWindowPixmap(pWindow); +} + +void +_fbSetWindowPixmap(WindowPtr pWindow, PixmapPtr pPixmap) +{ + pWindow->devPrivates[fbWinPrivateIndex].ptr = (pointer) pPixmap; +} + +Bool +fbSetupScreen(ScreenPtr pScreen, pointer pbits, /* pointer to screen bitmap */ + int xsize, /* in pixels */ + int ysize, int dpix, /* dots per inch */ + int dpiy, int width, /* pixel width of frame buffer */ + int bpp) +{ /* bits per pixel for screen */ + if (!fbAllocatePrivates(pScreen, (int *) 0)) + return FALSE; + pScreen->defColormap = FakeClientID(0); + /* let CreateDefColormap do whatever it wants for pixels */ + pScreen->blackPixel = pScreen->whitePixel = (Pixel) 0; + pScreen->QueryBestSize = fbQueryBestSize; + /* SaveScreen */ + pScreen->GetImage = fbGetImage; + pScreen->GetSpans = fbGetSpans; + pScreen->CreateWindow = fbCreateWindow; + pScreen->DestroyWindow = fbDestroyWindow; + pScreen->PositionWindow = fbPositionWindow; + pScreen->ChangeWindowAttributes = fbChangeWindowAttributes; + pScreen->RealizeWindow = fbMapWindow; + pScreen->UnrealizeWindow = fbUnmapWindow; + pScreen->PaintWindowBackground = fbPaintWindow; + pScreen->PaintWindowBorder = fbPaintWindow; + pScreen->CopyWindow = fbCopyWindow; + pScreen->CreatePixmap = fbCreatePixmap; + pScreen->DestroyPixmap = fbDestroyPixmap; + pScreen->RealizeFont = fbRealizeFont; + pScreen->UnrealizeFont = fbUnrealizeFont; + pScreen->CreateGC = fbCreateGC; + pScreen->CreateColormap = fbInitializeColormap; + pScreen->DestroyColormap = (void (*)(ColormapPtr)) NoopDDA; + pScreen->InstallColormap = fbInstallColormap; + pScreen->UninstallColormap = fbUninstallColormap; + pScreen->ListInstalledColormaps = fbListInstalledColormaps; + pScreen->StoreColors = (void (*)(ColormapPtr, int, xColorItem *)) NoopDDA; + pScreen->ResolveColor = fbResolveColor; + pScreen->BitmapToRegion = fbPixmapToRegion; + + pScreen->GetWindowPixmap = _fbGetWindowPixmap; + pScreen->SetWindowPixmap = _fbSetWindowPixmap; + + return TRUE; +} + +Bool +fbFinishScreenInit(ScreenPtr pScreen, + pointer pbits, + int xsize, int ysize, int dpix, int dpiy, int width, int bpp) +{ + VisualPtr visuals; + + DepthPtr depths; + + int nvisuals; + + int ndepths; + + int rootdepth; + + VisualID defaultVisual; + + int imagebpp = bpp; + +#ifdef FB_DEBUG + int stride; + + ysize -= 2; + stride = (width * bpp) / 8; + fbSetBits((FbStip *) pbits, stride / sizeof(FbStip), FB_HEAD_BITS); + pbits = (void *) ((char *) pbits + stride); + fbSetBits((FbStip *) ((char *) pbits + stride * ysize), + stride / sizeof(FbStip), FB_TAIL_BITS); +#endif + /* + * By default, a 24bpp screen will use 32bpp images, this avoids + * problems with many applications which just can't handle packed + * pixels. If you want real 24bit images, include a 24bpp + * format in the pixmap formats + */ + if (bpp == 24) { + int f; + + imagebpp = 32; + /* + * Check to see if we're advertising a 24bpp image format, + * in which case windows will use it in preference to a 32 bit + * format. + */ + for (f = 0; f < screenInfo.numPixmapFormats; f++) { + if (screenInfo.formats[f].bitsPerPixel == 24) { + imagebpp = 24; + break; + } + } + } + if (imagebpp == 32) { + fbGetScreenPrivate(pScreen)->win32bpp = bpp; + fbGetScreenPrivate(pScreen)->pix32bpp = bpp; + } + else { + fbGetScreenPrivate(pScreen)->win32bpp = 32; + fbGetScreenPrivate(pScreen)->pix32bpp = 32; + } + rootdepth = 0; + if (!fbInitVisuals(&visuals, &depths, &nvisuals, &ndepths, &rootdepth, + &defaultVisual, ((unsigned long) 1 << (imagebpp - 1)), + 8)) + return FALSE; + if (!miScreenInit(pScreen, pbits, xsize, ysize, dpix, dpiy, width, + rootdepth, ndepths, depths, + defaultVisual, nvisuals, visuals + )) + return FALSE; + /* overwrite miCloseScreen with our own */ + pScreen->CloseScreen = fbCloseScreen; + if (bpp == 24 && imagebpp == 32) { + pScreen->ModifyPixmapHeader = fb24_32ModifyPixmapHeader; + pScreen->CreateScreenResources = fb24_32CreateScreenResources; + } + return TRUE; +} diff --git a/fb/fbseg.c b/fb/fbseg.c new file mode 100644 index 0000000..dc984ed --- /dev/null +++ b/fb/fbseg.c @@ -0,0 +1,677 @@ +/* + * + * Copyright © 1998 Keith Packard + * + * 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, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include + +#include "fb.h" +#include "miline.h" + +#define fbBresShiftMask(mask,dir,bpp) ((bpp == FB_STIP_UNIT) ? 0 : \ + ((dir < 0) ? FbStipLeft(mask,bpp) : \ + FbStipRight(mask,bpp))) + +void +fbBresSolid(DrawablePtr pDrawable, + GCPtr pGC, + int dashOffset, + int signdx, + int signdy, + int axis, int x1, int y1, int e, int e1, int e3, int len) +{ + FbStip *dst; + + FbStride dstStride; + + int dstBpp; + + int dstXoff, dstYoff; + + FbGCPrivPtr pPriv = fbGetGCPrivate(pGC); + + FbStip and = (FbStip) pPriv->and; + + FbStip xor = (FbStip) pPriv->xor; + + FbStip mask, mask0; + + FbStip bits; + + fbGetStipDrawable(pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); + dst += ((y1 + dstYoff) * dstStride); + x1 = (x1 + dstXoff) * dstBpp; + dst += x1 >> FB_STIP_SHIFT; + x1 &= FB_STIP_MASK; + mask0 = FbStipMask(0, dstBpp); + mask = FbStipRight(mask0, x1); + if (signdx < 0) + mask0 = FbStipRight(mask0, FB_STIP_UNIT - dstBpp); + if (signdy < 0) + dstStride = -dstStride; + if (axis == X_AXIS) { + bits = 0; + while (len--) { + bits |= mask; + mask = fbBresShiftMask(mask, signdx, dstBpp); + if (!mask) { + *dst = FbDoMaskRRop(*dst, and, xor, bits); + bits = 0; + dst += signdx; + mask = mask0; + } + e += e1; + if (e >= 0) { + *dst = FbDoMaskRRop(*dst, and, xor, bits); + bits = 0; + dst += dstStride; + e += e3; + } + } + if (bits) + *dst = FbDoMaskRRop(*dst, and, xor, bits); + } + else { + while (len--) { + *dst = FbDoMaskRRop(*dst, and, xor, mask); + dst += dstStride; + e += e1; + if (e >= 0) { + e += e3; + mask = fbBresShiftMask(mask, signdx, dstBpp); + if (!mask) { + dst += signdx; + mask = mask0; + } + } + } + } +} + +void +fbBresDash(DrawablePtr pDrawable, + GCPtr pGC, + int dashOffset, + int signdx, + int signdy, int axis, int x1, int y1, int e, int e1, int e3, int len) +{ + FbStip *dst; + + FbStride dstStride; + + int dstBpp; + + int dstXoff, dstYoff; + + FbGCPrivPtr pPriv = fbGetGCPrivate(pGC); + + FbStip and = (FbStip) pPriv->and; + + FbStip xor = (FbStip) pPriv->xor; + + FbStip bgand = (FbStip) pPriv->bgand; + + FbStip bgxor = (FbStip) pPriv->bgxor; + + FbStip mask, mask0; + + FbDashDeclare; + int dashlen; + + Bool even; + + Bool doOdd; + + fbGetStipDrawable(pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); + doOdd = pGC->lineStyle == LineDoubleDash; + + FbDashInit(pGC, pPriv, dashOffset, dashlen, even); + + dst += ((y1 + dstYoff) * dstStride); + x1 = (x1 + dstXoff) * dstBpp; + dst += x1 >> FB_STIP_SHIFT; + x1 &= FB_STIP_MASK; + mask0 = FbStipMask(0, dstBpp); + mask = FbStipRight(mask0, x1); + if (signdx < 0) + mask0 = FbStipRight(mask0, FB_STIP_UNIT - dstBpp); + if (signdy < 0) + dstStride = -dstStride; + while (len--) { + if (even) + *dst = FbDoMaskRRop(*dst, and, xor, mask); + else if (doOdd) + *dst = FbDoMaskRRop(*dst, bgand, bgxor, mask); + if (axis == X_AXIS) { + mask = fbBresShiftMask(mask, signdx, dstBpp); + if (!mask) { + dst += signdx; + mask = mask0; + } + e += e1; + if (e >= 0) { + dst += dstStride; + e += e3; + } + } + else { + dst += dstStride; + e += e1; + if (e >= 0) { + e += e3; + mask = fbBresShiftMask(mask, signdx, dstBpp); + if (!mask) { + dst += signdx; + mask = mask0; + } + } + } + FbDashStep(dashlen, even); + } +} + +void +fbBresFill(DrawablePtr pDrawable, + GCPtr pGC, + int dashOffset, + int signdx, + int signdy, int axis, int x1, int y1, int e, int e1, int e3, int len) +{ + while (len--) { + fbFill(pDrawable, pGC, x1, y1, 1, 1); + if (axis == X_AXIS) { + x1 += signdx; + e += e1; + if (e >= 0) { + e += e3; + y1 += signdy; + } + } + else { + y1 += signdy; + e += e1; + if (e >= 0) { + e += e3; + x1 += signdx; + } + } + } +} + +static void +fbSetFg(DrawablePtr pDrawable, GCPtr pGC, Pixel fg) +{ + if (fg != pGC->fgPixel) { + DoChangeGC(pGC, GCForeground, (XID *) &fg, FALSE); + ValidateGC(pDrawable, pGC); + } +} + +void +fbBresFillDash(DrawablePtr pDrawable, + GCPtr pGC, + int dashOffset, + int signdx, + int signdy, + int axis, int x1, int y1, int e, int e1, int e3, int len) +{ + FbGCPrivPtr pPriv = fbGetGCPrivate(pGC); + + FbDashDeclare; + int dashlen; + + Bool even; + + Bool doOdd; + + Bool doBg; + + Pixel fg, bg; + + fg = pGC->fgPixel; + bg = pGC->bgPixel; + + /* whether to fill the odd dashes */ + doOdd = pGC->lineStyle == LineDoubleDash; + /* whether to switch fg to bg when filling odd dashes */ + doBg = doOdd && (pGC->fillStyle == FillSolid || + pGC->fillStyle == FillStippled); + + /* compute current dash position */ + FbDashInit(pGC, pPriv, dashOffset, dashlen, even); + + while (len--) { + if (even || doOdd) { + if (doBg) { + if (even) + fbSetFg(pDrawable, pGC, fg); + else + fbSetFg(pDrawable, pGC, bg); + } + fbFill(pDrawable, pGC, x1, y1, 1, 1); + } + if (axis == X_AXIS) { + x1 += signdx; + e += e1; + if (e >= 0) { + e += e3; + y1 += signdy; + } + } + else { + y1 += signdy; + e += e1; + if (e >= 0) { + e += e3; + x1 += signdx; + } + } + FbDashStep(dashlen, even); + } + if (doBg) + fbSetFg(pDrawable, pGC, fg); +} + +static void +fbBresSolid24RRop(DrawablePtr pDrawable, + GCPtr pGC, + int dashOffset, + int signdx, + int signdy, + int axis, int x1, int y1, int e, int e1, int e3, int len) +{ + FbStip *dst; + + FbStride dstStride; + + int dstBpp; + + int dstXoff, dstYoff; + + FbGCPrivPtr pPriv = fbGetGCPrivate(pGC); + + FbStip and = pPriv->and; + + FbStip xor = pPriv->xor; + + FbStip leftMask, rightMask; + + int nl; + + FbStip *d; + + int x; + + int rot; + + FbStip andT, xorT; + + fbGetStipDrawable(pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); + dst += ((y1 + dstYoff) * dstStride); + x1 = (x1 + dstXoff) * 24; + if (signdy < 0) + dstStride = -dstStride; + signdx *= 24; + while (len--) { + d = dst + (x1 >> FB_STIP_SHIFT); + x = x1 & FB_STIP_MASK; + rot = FbFirst24Rot(x); + andT = FbRot24Stip(and, rot); + xorT = FbRot24Stip(xor, rot); + FbMaskStip(x, 24, leftMask, nl, rightMask); + if (leftMask) { + *d = FbDoMaskRRop(*d, andT, xorT, leftMask); + d++; + andT = FbNext24Stip(andT); + xorT = FbNext24Stip(xorT); + } + if (rightMask) + *d = FbDoMaskRRop(*d, andT, xorT, rightMask); + if (axis == X_AXIS) { + x1 += signdx; + e += e1; + if (e >= 0) { + e += e3; + dst += dstStride; + } + } + else { + dst += dstStride; + e += e1; + if (e >= 0) { + e += e3; + x1 += signdx; + } + } + } +} + +static void +fbBresDash24RRop(DrawablePtr pDrawable, + GCPtr pGC, + int dashOffset, + int signdx, + int signdy, + int axis, int x1, int y1, int e, int e1, int e3, int len) +{ + FbStip *dst; + + FbStride dstStride; + + int dstBpp; + + int dstXoff, dstYoff; + + FbGCPrivPtr pPriv = fbGetGCPrivate(pGC); + + FbStip andT, xorT; + + FbStip fgand = pPriv->and; + + FbStip fgxor = pPriv->xor; + + FbStip bgand = pPriv->bgand; + + FbStip bgxor = pPriv->bgxor; + + FbStip leftMask, rightMask; + + int nl; + + FbStip *d; + + int x; + + int rot; + + FbDashDeclare; + int dashlen; + + Bool even; + + Bool doOdd; + + fbGetStipDrawable(pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); + doOdd = pGC->lineStyle == LineDoubleDash; + + /* compute current dash position */ + FbDashInit(pGC, pPriv, dashOffset, dashlen, even); + + dst += ((y1 + dstYoff) * dstStride); + x1 = (x1 + dstXoff) * 24; + if (signdy < 0) + dstStride = -dstStride; + signdx *= 24; + while (len--) { + if (even || doOdd) { + if (even) { + andT = fgand; + xorT = fgxor; + } + else { + andT = bgand; + xorT = bgxor; + } + d = dst + (x1 >> FB_STIP_SHIFT); + x = x1 & FB_STIP_MASK; + rot = FbFirst24Rot(x); + andT = FbRot24Stip(andT, rot); + xorT = FbRot24Stip(xorT, rot); + FbMaskStip(x, 24, leftMask, nl, rightMask); + if (leftMask) { + *d = FbDoMaskRRop(*d, andT, xorT, leftMask); + d++; + andT = FbNext24Stip(andT); + xorT = FbNext24Stip(xorT); + } + if (rightMask) + *d = FbDoMaskRRop(*d, andT, xorT, rightMask); + } + if (axis == X_AXIS) { + x1 += signdx; + e += e1; + if (e >= 0) { + e += e3; + dst += dstStride; + } + } + else { + dst += dstStride; + e += e1; + if (e >= 0) { + e += e3; + x1 += signdx; + } + } + FbDashStep(dashlen, even); + } +} + +/* + * For drivers that want to bail drawing some lines, this + * function takes care of selecting the appropriate rasterizer + * based on the contents of the specified GC. + */ + +FbBres * +fbSelectBres(DrawablePtr pDrawable, GCPtr pGC) +{ + FbGCPrivPtr pPriv = fbGetGCPrivate(pGC); + + int dstBpp = pDrawable->bitsPerPixel; + + FbBres *bres; + + if (pGC->lineStyle == LineSolid) { + bres = fbBresFill; + if (pGC->fillStyle == FillSolid) { + bres = fbBresSolid; + if (dstBpp == 24) + bres = fbBresSolid24RRop; + if (pPriv->and == 0) { + switch (dstBpp) { + case 8: + bres = fbBresSolid8; + break; + case 16: + bres = fbBresSolid16; + break; + case 24: + bres = fbBresSolid24; + break; + case 32: + bres = fbBresSolid32; + break; + } + } + } + } + else { + bres = fbBresFillDash; + if (pGC->fillStyle == FillSolid) { + bres = fbBresDash; + if (dstBpp == 24) + bres = fbBresDash24RRop; + if (pPriv->and == 0 && + (pGC->lineStyle == LineOnOffDash || pPriv->bgand == 0)) { + switch (dstBpp) { + case 8: + bres = fbBresDash8; + break; + case 16: + bres = fbBresDash16; + break; + case 24: + bres = fbBresDash24; + break; + case 32: + bres = fbBresDash32; + break; + } + } + } + } + return bres; +} + +void +fbSegment(DrawablePtr pDrawable, + GCPtr pGC, + int x1, int y1, int x2, int y2, Bool drawLast, int *dashOffset) +{ + FbBres *bres; + + RegionPtr pClip = fbGetCompositeClip(pGC); + + BoxPtr pBox; + + int nBox; + + int adx; /* abs values of dx and dy */ + + int ady; + + int signdx; /* sign of dx and dy */ + + int signdy; + + int e, e1, e2, e3; /* bresenham error and increments */ + + int len; /* length of segment */ + + int axis; /* major axis */ + + int octant; + + int dashoff; + + int doff; + + unsigned int bias = miGetZeroLineBias(pDrawable->pScreen); + + unsigned int oc1; /* outcode of point 1 */ + + unsigned int oc2; /* outcode of point 2 */ + + nBox = REGION_NUM_RECTS(pClip); + pBox = REGION_RECTS(pClip); + + bres = fbSelectBres(pDrawable, pGC); + + CalcLineDeltas(x1, y1, x2, y2, adx, ady, signdx, signdy, 1, 1, octant); + + if (adx > ady) { + axis = X_AXIS; + e1 = ady << 1; + e2 = e1 - (adx << 1); + e = e1 - adx; + len = adx; + } + else { + axis = Y_AXIS; + e1 = adx << 1; + e2 = e1 - (ady << 1); + e = e1 - ady; + SetYMajorOctant(octant); + len = ady; + } + + FIXUP_ERROR(e, octant, bias); + + /* + * Adjust error terms to compare against zero + */ + e3 = e2 - e1; + e = e - e1; + + /* we have bresenham parameters and two points. + all we have to do now is clip and draw. + */ + + if (drawLast) + len++; + dashoff = *dashOffset; + *dashOffset = dashoff + len; + while (nBox--) { + oc1 = 0; + oc2 = 0; + OUTCODES(oc1, x1, y1, pBox); + OUTCODES(oc2, x2, y2, pBox); + if ((oc1 | oc2) == 0) { + (*bres) (pDrawable, pGC, dashoff, + signdx, signdy, axis, x1, y1, e, e1, e3, len); + break; + } + else if (oc1 & oc2) { + pBox++; + } + else { + int new_x1 = x1, new_y1 = y1, new_x2 = x2, new_y2 = y2; + + int clip1 = 0, clip2 = 0; + + int clipdx, clipdy; + + int err; + + if (miZeroClipLine(pBox->x1, pBox->y1, pBox->x2 - 1, + pBox->y2 - 1, + &new_x1, &new_y1, &new_x2, &new_y2, + adx, ady, &clip1, &clip2, + octant, bias, oc1, oc2) == -1) { + pBox++; + continue; + } + + if (axis == X_AXIS) + len = abs(new_x2 - new_x1); + else + len = abs(new_y2 - new_y1); + if (clip2 != 0 || drawLast) + len++; + if (len) { + /* unwind bresenham error term to first point */ + doff = dashoff; + err = e; + if (clip1) { + clipdx = abs(new_x1 - x1); + clipdy = abs(new_y1 - y1); + if (axis == X_AXIS) { + doff += clipdx; + err += e3 * clipdy + e1 * clipdx; + } + else { + doff += clipdy; + err += e3 * clipdx + e1 * clipdy; + } + } + (*bres) (pDrawable, pGC, doff, + signdx, signdy, axis, new_x1, new_y1, + err, e1, e3, len); + } + pBox++; + } + } /* while (nBox--) */ +} diff --git a/fb/fbsetsp.c b/fb/fbsetsp.c new file mode 100644 index 0000000..93835d5 --- /dev/null +++ b/fb/fbsetsp.c @@ -0,0 +1,93 @@ +/* + * + * Copyright © 1998 Keith Packard + * + * 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, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "fb.h" + +void +fbSetSpans(DrawablePtr pDrawable, + GCPtr pGC, + char *src, DDXPointPtr ppt, int *pwidth, int nspans, int fSorted) +{ + FbGCPrivPtr pPriv = fbGetGCPrivate(pGC); + + RegionPtr pClip = fbGetCompositeClip(pGC); + + FbBits *dst, *d, *s; + + FbStride dstStride; + + int dstBpp; + + int dstXoff, dstYoff; + + BoxPtr pbox; + + int n; + + int xoff; + + int x1, x2; + + if (pDrawable->bitsPerPixel != BitsPerPixel(pDrawable->depth)) { + fb24_32SetSpans(pDrawable, pGC, src, ppt, pwidth, nspans, fSorted); + return; + } + fbGetDrawable(pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); + while (nspans--) { + d = dst + (ppt->y + dstYoff) * dstStride; + xoff = (int) (((long) src) & (FB_MASK >> 3)); + s = (FbBits *) (src - xoff); + xoff <<= 3; + n = REGION_NUM_RECTS(pClip); + pbox = REGION_RECTS(pClip); + while (n--) { + if (pbox->y1 > ppt->y) + break; + if (pbox->y2 > ppt->y) { + x1 = ppt->x; + x2 = x1 + *pwidth; + if (pbox->x1 > x1) + x1 = pbox->x1; + if (pbox->x2 < x2) + x2 = pbox->x2; + if (x1 < x2) + fbBlt((FbBits *) s, + 0, + (x1 - ppt->x) * dstBpp + xoff, + d, + dstStride, + (x1 + dstXoff) * dstBpp, + (x2 - x1) * dstBpp, + 1, pGC->alu, pPriv->pm, dstBpp, FALSE, FALSE); + } + } + src += PixmapBytePad(*pwidth, pDrawable->depth); + ppt++; + pwidth++; + } + fbValidateDrawable(pDrawable); +} diff --git a/fb/fbsolid.c b/fb/fbsolid.c new file mode 100644 index 0000000..f014a7b --- /dev/null +++ b/fb/fbsolid.c @@ -0,0 +1,187 @@ +/* + * + * Copyright © 1998 Keith Packard + * + * 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, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD 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. + */ + +#define FbSelectPart(xor,o,t) xor + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "fb.h" + +void +fbSolid(FbBits * dst, + FbStride dstStride, + int dstX, int bpp, int width, int height, FbBits and, FbBits xor) +{ + FbBits startmask, endmask; + + int n, nmiddle; + + int startbyte, endbyte; + + if (bpp == 24 && (!FbCheck24Pix(and) || !FbCheck24Pix(xor))) { + fbSolid24(dst, dstStride, dstX, width, height, and, xor); + return; + } + dst += dstX >> FB_SHIFT; + dstX &= FB_MASK; + FbMaskBitsBytes(dstX, width, and == 0, startmask, startbyte, + nmiddle, endmask, endbyte); + if (startmask) + dstStride--; + dstStride -= nmiddle; + while (height--) { + if (startmask) { + FbDoLeftMaskByteRRop(dst, startbyte, startmask, and, xor); + dst++; + } + n = nmiddle; + if (!and) + while (n--) + *dst++ = xor; + else + while (n--) { + *dst = FbDoRRop(*dst, and, xor); + dst++; + } + if (endmask) + FbDoRightMaskByteRRop(dst, endbyte, endmask, and, xor); + dst += dstStride; + } +} + +void +fbSolid24(FbBits * dst, + FbStride dstStride, + int dstX, int width, int height, FbBits and, FbBits xor) +{ + FbBits startmask, endmask; + + FbBits xor0 = 0, xor1 = 0, xor2 = 0; + + FbBits and0 = 0, and1 = 0, and2 = 0; + + FbBits xorS = 0, andS = 0, xorE = 0, andE = 0; + + int n, nmiddle; + + int rotS, rot; + + dst += dstX >> FB_SHIFT; + dstX &= FB_MASK; + /* + * Rotate pixel values this far across the word to align on + * screen pixel boundaries + */ + rot = FbFirst24Rot(dstX); + FbMaskBits(dstX, width, startmask, nmiddle, endmask); + if (startmask) + dstStride--; + dstStride -= nmiddle; + + /* + * Precompute rotated versions of the rasterop values + */ + rotS = rot; + xor = FbRot24(xor, rotS); + and = FbRot24(and, rotS); + if (startmask) { + xorS = xor; + andS = and; + xor = FbNext24Pix(xor); + and = FbNext24Pix(and); + } + + if (nmiddle) { + xor0 = xor; + and0 = and; + xor1 = FbNext24Pix(xor0); + and1 = FbNext24Pix(and0); + xor2 = FbNext24Pix(xor1); + and2 = FbNext24Pix(and1); + } + + if (endmask) { + switch (nmiddle % 3) { + case 0: + xorE = xor; + andE = and; + break; + case 1: + xorE = xor1; + andE = and1; + break; + case 2: + xorE = xor2; + andE = and2; + break; + } + } + + while (height--) { + if (startmask) { + *dst = FbDoMaskRRop(*dst, andS, xorS, startmask); + dst++; + } + n = nmiddle; + if (!and0) { + while (n >= 3) { + *dst++ = xor0; + *dst++ = xor1; + *dst++ = xor2; + n -= 3; + } + if (n) { + *dst++ = xor0; + n--; + if (n) { + *dst++ = xor1; + } + } + } + else { + while (n >= 3) { + *dst = FbDoRRop(*dst, and0, xor0); + dst++; + *dst = FbDoRRop(*dst, and1, xor1); + dst++; + *dst = FbDoRRop(*dst, and2, xor2); + dst++; + n -= 3; + } + if (n) { + *dst = FbDoRRop(*dst, and0, xor0); + dst++; + n--; + if (n) { + *dst = FbDoRRop(*dst, and1, xor1); + dst++; + } + } + } + if (endmask) + *dst = FbDoMaskRRop(*dst, andE, xorE, endmask); + dst += dstStride; + } +} diff --git a/fb/fbstipple.c b/fb/fbstipple.c new file mode 100644 index 0000000..cdc13e1 --- /dev/null +++ b/fb/fbstipple.c @@ -0,0 +1,277 @@ +/* + * + * Copyright © 1998 Keith Packard + * + * 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, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "fb.h" + +/* + * This is a slight abuse of the preprocessor to generate repetitive + * code, the idea is to generate code for each case of a copy-mode + * transparent stipple + */ +#define LaneCases1(c,a) case c: \ + while (n--) { (void)FbLaneCase(c,a); a++; } \ + break +#define LaneCases2(c,a) LaneCases1(c,a); LaneCases1(c+1,a) +#define LaneCases4(c,a) LaneCases2(c,a); LaneCases2(c+2,a) +#define LaneCases8(c,a) LaneCases4(c,a); LaneCases4(c+4,a) +#define LaneCases16(c,a) LaneCases8(c,a); LaneCases8(c+8,a) +#define LaneCases32(c,a) LaneCases16(c,a); LaneCases16(c+16,a) +#define LaneCases64(c,a) LaneCases32(c,a); LaneCases32(c+32,a) +#define LaneCases128(c,a) LaneCases64(c,a); LaneCases64(c+64,a) +#define LaneCases256(c,a) LaneCases128(c,a); LaneCases128(c+128,a) + +#if FB_SHIFT == 6 +#define LaneCases(a) LaneCases256(0,a) +#endif + +#if FB_SHIFT == 5 +#define LaneCases(a) LaneCases16(0,a) +#endif + +/* + * Repeat a transparent stipple across a scanline n times + */ + +void +fbTransparentSpan(FbBits * dst, FbBits stip, FbBits fgxor, int n) +{ + FbStip s; + + s = ((FbStip) (stip) & 0x01); + s |= ((FbStip) (stip >> 8) & 0x02); + s |= ((FbStip) (stip >> 16) & 0x04); + s |= ((FbStip) (stip >> 24) & 0x08); +#if FB_SHIFT > 5 + s |= ((FbStip) (stip >> 32) & 0x10); + s |= ((FbStip) (stip >> 40) & 0x20); + s |= ((FbStip) (stip >> 48) & 0x40); + s |= ((FbStip) (stip >> 56) & 0x80); +#endif + switch (s) { + LaneCases(dst); + } +} + +void +fbEvenStipple(FbBits * dst, + FbStride dstStride, + int dstX, + int dstBpp, + int width, + int height, + FbStip * stip, + FbStride stipStride, + int stipHeight, + FbBits fgand, + FbBits fgxor, FbBits bgand, FbBits bgxor, int xRot, int yRot) +{ + FbBits startmask, endmask; + + FbBits mask, and, xor; + + int nmiddle, n; + + FbStip *s, *stipEnd, bits; + + int rot, stipX, stipY; + + int pixelsPerDst; + + const FbBits *fbBits; + + Bool transparent; + + int startbyte, endbyte; + + /* + * Check for a transparent stipple (stencil) + */ + transparent = FALSE; + if (dstBpp >= 8 && fgand == 0 && bgand == FB_ALLONES && bgxor == 0) + transparent = TRUE; + + pixelsPerDst = FB_UNIT / dstBpp; + /* + * Adjust dest pointers + */ + dst += dstX >> FB_SHIFT; + dstX &= FB_MASK; + FbMaskBitsBytes(dstX, width, fgand == 0 && bgand == 0, + startmask, startbyte, nmiddle, endmask, endbyte); + + if (startmask) + dstStride--; + dstStride -= nmiddle; + + xRot *= dstBpp; + /* + * Compute stip start scanline and rotation parameters + */ + stipEnd = stip + stipStride * stipHeight; + modulus(-yRot, stipHeight, stipY); + s = stip + stipStride * stipY; + modulus(-xRot, FB_UNIT, stipX); + rot = stipX; + + /* + * Get pointer to stipple mask array for this depth + */ + /* fbStippleTable covers all valid bpp (4,8,16,32) */ + fbBits = fbStippleTable[pixelsPerDst]; + + while (height--) { + /* + * Extract stipple bits for this scanline; + */ + bits = *s; + s += stipStride; + if (s == stipEnd) + s = stip; +#if FB_UNIT > 32 + if (pixelsPerDst == 16) + mask = FbStipple16Bits(FbLeftStipBits(bits, 16)); + else +#endif + mask = fbBits[FbLeftStipBits(bits, pixelsPerDst)]; + /* + * Rotate into position and compute reduced rop values + */ + mask = FbRotLeft(mask, rot); + and = (fgand & mask) | (bgand & ~mask); + xor = (fgxor & mask) | (bgxor & ~mask); + + if (transparent) { + if (startmask) { + fbTransparentSpan(dst, mask & startmask, fgxor, 1); + dst++; + } + fbTransparentSpan(dst, mask, fgxor, nmiddle); + dst += nmiddle; + if (endmask) + fbTransparentSpan(dst, mask & endmask, fgxor, 1); + } + else + { + /* + * Fill scanline + */ + if (startmask) { + FbDoLeftMaskByteRRop(dst, startbyte, startmask, and, xor); + dst++; + } + n = nmiddle; + if (!and) + while (n--) + *dst++ = xor; + else { + while (n--) { + *dst = FbDoRRop(*dst, and, xor); + dst++; + } + } + if (endmask) + FbDoRightMaskByteRRop(dst, endbyte, endmask, and, xor); + } + dst += dstStride; + } +} + +void +fbOddStipple(FbBits * dst, + FbStride dstStride, + int dstX, + int dstBpp, + int width, + int height, + FbStip * stip, + FbStride stipStride, + int stipWidth, + int stipHeight, + FbBits fgand, + FbBits fgxor, FbBits bgand, FbBits bgxor, int xRot, int yRot) +{ + int stipX, stipY, sx; + + int widthTmp; + + int h, w; + + int x, y; + + modulus(-yRot, stipHeight, stipY); + modulus(dstX / dstBpp - xRot, stipWidth, stipX); + y = 0; + while (height) { + h = stipHeight - stipY; + if (h > height) + h = height; + height -= h; + widthTmp = width; + x = dstX; + sx = stipX; + while (widthTmp) { + w = (stipWidth - sx) * dstBpp; + if (w > widthTmp) + w = widthTmp; + widthTmp -= w; + fbBltOne(stip + stipY * stipStride, + stipStride, + sx, + dst + y * dstStride, + dstStride, x, dstBpp, w, h, fgand, fgxor, bgand, bgxor); + x += w; + sx = 0; + } + y += h; + stipY = 0; + } +} + +void +fbStipple(FbBits * dst, + FbStride dstStride, + int dstX, + int dstBpp, + int width, + int height, + FbStip * stip, + FbStride stipStride, + int stipWidth, + int stipHeight, + Bool even, + FbBits fgand, + FbBits fgxor, FbBits bgand, FbBits bgxor, int xRot, int yRot) +{ + if (even) + fbEvenStipple(dst, dstStride, dstX, dstBpp, width, height, + stip, stipStride, stipHeight, + fgand, fgxor, bgand, bgxor, xRot, yRot); + else + fbOddStipple(dst, dstStride, dstX, dstBpp, width, height, + stip, stipStride, stipWidth, stipHeight, + fgand, fgxor, bgand, bgxor, xRot, yRot); +} diff --git a/fb/fbtile.c b/fb/fbtile.c new file mode 100644 index 0000000..78f06b1 --- /dev/null +++ b/fb/fbtile.c @@ -0,0 +1,161 @@ +/* + * Copyright © 1998 Keith Packard + * + * 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, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "fb.h" + +/* + * Accelerated tile fill -- tile width is a power of two not greater + * than FB_UNIT + */ + +void +fbEvenTile(FbBits * dst, + FbStride dstStride, + int dstX, + int width, + int height, + FbBits * tile, + int tileHeight, int alu, FbBits pm, int xRot, int yRot) +{ + FbBits *t, *tileEnd, bits; + FbBits startmask, endmask; + FbBits and, xor; + int n, nmiddle; + int tileX, tileY; + int rot; + int startbyte, endbyte; + + dst += dstX >> FB_SHIFT; + dstX &= FB_MASK; + FbMaskBitsBytes(dstX, width, FbDestInvarientRop(alu, pm), + startmask, startbyte, nmiddle, endmask, endbyte); + if (startmask) + dstStride--; + dstStride -= nmiddle; + + /* + * Compute tile start scanline and rotation parameters + */ + tileEnd = tile + tileHeight; + modulus(-yRot, tileHeight, tileY); + t = tile + tileY; + modulus(-xRot, FB_UNIT, tileX); + rot = tileX; + + while (height--) { + + /* + * Pick up bits for this scanline + */ + bits = *t++; + if (t == tileEnd) + t = tile; + bits = FbRotLeft(bits, rot); + and = fbAnd(alu, bits, pm); + xor = fbXor(alu, bits, pm); + + if (startmask) { + FbDoLeftMaskByteRRop(dst, startbyte, startmask, and, xor); + dst++; + } + n = nmiddle; + if (!and) + while (n--) + *dst++ = xor; + else + while (n--) { + *dst = FbDoRRop(*dst, and, xor); + dst++; + } + if (endmask) + FbDoRightMaskByteRRop(dst, endbyte, endmask, and, xor); + dst += dstStride; + } +} + +void +fbOddTile(FbBits * dst, + FbStride dstStride, + int dstX, + int width, + int height, + FbBits * tile, + FbStride tileStride, + int tileWidth, + int tileHeight, int alu, FbBits pm, int bpp, int xRot, int yRot) +{ + int tileX, tileY; + int widthTmp; + int h, w; + int x, y; + + modulus(-yRot, tileHeight, tileY); + y = 0; + while (height) { + h = tileHeight - tileY; + if (h > height) + h = height; + height -= h; + widthTmp = width; + x = dstX; + modulus(dstX - xRot, tileWidth, tileX); + while (widthTmp) { + w = tileWidth - tileX; + if (w > widthTmp) + w = widthTmp; + widthTmp -= w; + fbBlt(tile + tileY * tileStride, + tileStride, + tileX, + dst + y * dstStride, + dstStride, x, w, h, alu, pm, bpp, FALSE, FALSE); + x += w; + tileX = 0; + } + y += h; + tileY = 0; + } +} + +void +fbTile(FbBits * dst, + FbStride dstStride, + int dstX, + int width, + int height, + FbBits * tile, + FbStride tileStride, + int tileWidth, + int tileHeight, int alu, FbBits pm, int bpp, int xRot, int yRot) +{ + if (FbEvenTile(tileWidth)) + fbEvenTile(dst, dstStride, dstX, width, height, + tile, tileHeight, alu, pm, xRot, yRot); + else + fbOddTile(dst, dstStride, dstX, width, height, + tile, tileStride, tileWidth, tileHeight, + alu, pm, bpp, xRot, yRot); +} diff --git a/fb/fbtrap.c b/fb/fbtrap.c new file mode 100644 index 0000000..a025223 --- /dev/null +++ b/fb/fbtrap.c @@ -0,0 +1,239 @@ +/* + * + * Copyright © 2004 Keith Packard + * + * 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, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "fb.h" + + +#include "picturestr.h" +#include "mipict.h" +#include "renderedge.h" +#include "fbpict.h" + +void +fbAddTraps(PicturePtr pPicture, + INT16 x_off, INT16 y_off, int ntrap, xTrap * traps) +{ + FbBits *buf; + + int bpp; + int width; + int stride; + int height; + int pxoff, pyoff; + + xFixed x_off_fixed; + xFixed y_off_fixed; + + RenderEdge l, r; + + xFixed t, b; + + fbGetDrawable(pPicture->pDrawable, buf, stride, bpp, pxoff, pyoff); + + width = pPicture->pDrawable->width; + height = pPicture->pDrawable->height; + x_off += pxoff; + y_off += pyoff; + + x_off_fixed = IntToxFixed(x_off); + y_off_fixed = IntToxFixed(y_off); + + while (ntrap--) { + t = traps->top.y + y_off_fixed; + if (t < 0) + t = 0; + t = RenderSampleCeilY(t, bpp); + + b = traps->bot.y + y_off_fixed; + if (xFixedToInt(b) >= height) + b = IntToxFixed(height) - 1; + b = RenderSampleFloorY(b, bpp); + + if (b >= t) { + /* initialize edge walkers */ + RenderEdgeInit(&l, bpp, t, + traps->top.l + x_off_fixed, + traps->top.y + y_off_fixed, + traps->bot.l + x_off_fixed, + traps->bot.y + y_off_fixed); + + RenderEdgeInit(&r, bpp, t, + traps->top.r + x_off_fixed, + traps->top.y + y_off_fixed, + traps->bot.r + x_off_fixed, + traps->bot.y + y_off_fixed); + + fbRasterizeEdges(buf, bpp, width, stride, &l, &r, t, b); + } + traps++; + } +} + +void +fbRasterizeTrapezoid(PicturePtr pPicture, + xTrapezoid * trap, int x_off, int y_off) +{ + FbBits *buf; + + int bpp; + + int width; + + int stride; + + int height; + + int pxoff, pyoff; + + xFixed x_off_fixed _X_UNUSED; + xFixed y_off_fixed; + + RenderEdge l, r; + + xFixed t, b; + + fbGetDrawable(pPicture->pDrawable, buf, stride, bpp, pxoff, pyoff); + + width = pPicture->pDrawable->width; + height = pPicture->pDrawable->height; + x_off += pxoff; + y_off += pyoff; + + x_off_fixed = IntToxFixed(x_off); + y_off_fixed = IntToxFixed(y_off); + t = trap->top + y_off_fixed; + if (t < 0) + t = 0; + t = RenderSampleCeilY(t, bpp); + + b = trap->bottom + y_off_fixed; + if (xFixedToInt(b) >= height) + b = IntToxFixed(height) - 1; + b = RenderSampleFloorY(b, bpp); + + if (b >= t) { + /* initialize edge walkers */ + RenderLineFixedEdgeInit(&l, bpp, t, &trap->left, x_off, y_off); + RenderLineFixedEdgeInit(&r, bpp, t, &trap->right, x_off, y_off); + + fbRasterizeEdges(buf, bpp, width, stride, &l, &r, t, b); + } +} + +static int +_GreaterY(xPointFixed * a, xPointFixed * b) +{ + if (a->y == b->y) + return a->x > b->x; + return a->y > b->y; +} + +/* + * Note that the definition of this function is a bit odd because + * of the X coordinate space (y increasing downwards). + */ +static int +_Clockwise(xPointFixed * ref, xPointFixed * a, xPointFixed * b) +{ + xPointFixed ad, bd; + + ad.x = a->x - ref->x; + ad.y = a->y - ref->y; + bd.x = b->x - ref->x; + bd.y = b->y - ref->y; + + return ((xFixed_32_32) bd.y * ad.x - (xFixed_32_32) ad.y * bd.x) < 0; +} + +/* FIXME -- this could be made more efficient */ +void +fbAddTriangles(PicturePtr pPicture, + INT16 x_off, INT16 y_off, int ntri, xTriangle * tris) +{ + xPointFixed *top, *left, *right, *tmp; + + xTrapezoid trap; + + for (; ntri; ntri--, tris++) { + top = &tris->p1; + left = &tris->p2; + right = &tris->p3; + if (_GreaterY(top, left)) { + tmp = left; + left = top; + top = tmp; + } + if (_GreaterY(top, right)) { + tmp = right; + right = top; + top = tmp; + } + if (_Clockwise(top, right, left)) { + tmp = right; + right = left; + left = tmp; + } + + /* + * Two cases: + * + * + + + * / \ / \ + * / \ / \ + * / + + \ + * / -- -- \ + * / -- -- \ + * / --- --- \ + * +-- --+ + */ + + trap.top = top->y; + trap.left.p1 = *top; + trap.left.p2 = *left; + trap.right.p1 = *top; + trap.right.p2 = *right; + if (right->y < left->y) + trap.bottom = right->y; + else + trap.bottom = left->y; + fbRasterizeTrapezoid(pPicture, &trap, x_off, y_off); + if (right->y < left->y) { + trap.top = right->y; + trap.bottom = left->y; + trap.right.p1 = *right; + trap.right.p2 = *left; + } + else { + trap.top = left->y; + trap.bottom = right->y; + trap.left.p1 = *left; + trap.left.p2 = *right; + } + fbRasterizeTrapezoid(pPicture, &trap, x_off, y_off); + } +} + diff --git a/fb/fbutil.c b/fb/fbutil.c new file mode 100644 index 0000000..28a70d7 --- /dev/null +++ b/fb/fbutil.c @@ -0,0 +1,293 @@ +/* + * Copyright © 1998 Keith Packard + * + * 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, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "fb.h" + +FbBits +fbReplicatePixel(Pixel p, int bpp) +{ + FbBits b = p; + + b &= FbFullMask(bpp); + while (bpp < FB_UNIT) { + b |= b << bpp; + bpp <<= 1; + } + return b; +} + +#define O 0 +#define I FB_ALLONES + +const FbMergeRopRec FbMergeRopBits[16] = { + {O, O, O, O}, /* clear 0x0 0 */ + {I, O, O, O}, /* and 0x1 src AND dst */ + {I, O, I, O}, /* andReverse 0x2 src AND NOT dst */ + {O, O, I, O}, /* copy 0x3 src */ + {I, I, O, O}, /* andInverted 0x4 NOT src AND dst */ + {O, I, O, O}, /* noop 0x5 dst */ + {O, I, I, O}, /* xor 0x6 src XOR dst */ + {I, I, I, O}, /* or 0x7 src OR dst */ + {I, I, I, I}, /* nor 0x8 NOT src AND NOT dst */ + {O, I, I, I}, /* equiv 0x9 NOT src XOR dst */ + {O, I, O, I}, /* invert 0xa NOT dst */ + {I, I, O, I}, /* orReverse 0xb src OR NOT dst */ + {O, O, I, I}, /* copyInverted 0xc NOT src */ + {I, O, I, I}, /* orInverted 0xd NOT src OR dst */ + {I, O, O, I}, /* nand 0xe NOT src OR NOT dst */ + {O, O, O, I}, /* set 0xf 1 */ +}; + +/* + * Stipple masks are independent of bit/byte order as long + * as bitorder == byteorder. FB doesn't handle the case + * where these differ + */ +#define BitsMask(x,w) ((FB_ALLONES << ((x) & FB_MASK)) & \ + (FB_ALLONES >> ((FB_UNIT - ((x) + (w))) & FB_MASK))) + +#define Mask(x,w) BitsMask((x)*(w),(w)) + +#define SelMask(b,n,w) ((((b) >> n) & 1) * Mask(n,w)) + +#define C1(b,w) \ + (SelMask(b,0,w)) + +#define C2(b,w) \ + (SelMask(b,0,w) | \ + SelMask(b,1,w)) + +#define C4(b,w) \ + (SelMask(b,0,w) | \ + SelMask(b,1,w) | \ + SelMask(b,2,w) | \ + SelMask(b,3,w)) + +#define C8(b,w) \ + (SelMask(b,0,w) | \ + SelMask(b,1,w) | \ + SelMask(b,2,w) | \ + SelMask(b,3,w) | \ + SelMask(b,4,w) | \ + SelMask(b,5,w) | \ + SelMask(b,6,w) | \ + SelMask(b,7,w)) + +#if FB_UNIT == 16 +#define fbStipple16Bits 0 +#define fbStipple8Bits 0 +const FbBits fbStipple4Bits[16] = { + C4(0, 4), C4(1, 4), C4(2, 4), C4(3, 4), C4(4, 4), C4(5, 4), + C4(6, 4), C4(7, 4), C4(8, 4), C4(9, 4), C4(10, 4), C4(11, 4), + C4(12, 4), C4(13, 4), C4(14, 4), C4(15, 4), +}; + +const FbBits fbStipple2Bits[4] = { + C2(0, 8), C2(1, 8), C2(2, 8), C2(3, 8), +}; + +const FbBits fbStipple1Bits[2] = { + C1(0, 16), C1(1, 16), +}; +#endif +#if FB_UNIT == 32 +#define fbStipple16Bits 0 +const FbBits fbStipple8Bits[256] = { + C8(0, 4), C8(1, 4), C8(2, 4), C8(3, 4), C8(4, 4), C8(5, 4), + C8(6, 4), C8(7, 4), C8(8, 4), C8(9, 4), C8(10, 4), C8(11, 4), + C8(12, 4), C8(13, 4), C8(14, 4), C8(15, 4), C8(16, 4), C8(17, 4), + C8(18, 4), C8(19, 4), C8(20, 4), C8(21, 4), C8(22, 4), C8(23, 4), + C8(24, 4), C8(25, 4), C8(26, 4), C8(27, 4), C8(28, 4), C8(29, 4), + C8(30, 4), C8(31, 4), C8(32, 4), C8(33, 4), C8(34, 4), C8(35, 4), + C8(36, 4), C8(37, 4), C8(38, 4), C8(39, 4), C8(40, 4), C8(41, 4), + C8(42, 4), C8(43, 4), C8(44, 4), C8(45, 4), C8(46, 4), C8(47, 4), + C8(48, 4), C8(49, 4), C8(50, 4), C8(51, 4), C8(52, 4), C8(53, 4), + C8(54, 4), C8(55, 4), C8(56, 4), C8(57, 4), C8(58, 4), C8(59, 4), + C8(60, 4), C8(61, 4), C8(62, 4), C8(63, 4), C8(64, 4), C8(65, 4), + C8(66, 4), C8(67, 4), C8(68, 4), C8(69, 4), C8(70, 4), C8(71, 4), + C8(72, 4), C8(73, 4), C8(74, 4), C8(75, 4), C8(76, 4), C8(77, 4), + C8(78, 4), C8(79, 4), C8(80, 4), C8(81, 4), C8(82, 4), C8(83, 4), + C8(84, 4), C8(85, 4), C8(86, 4), C8(87, 4), C8(88, 4), C8(89, 4), + C8(90, 4), C8(91, 4), C8(92, 4), C8(93, 4), C8(94, 4), C8(95, 4), + C8(96, 4), C8(97, 4), C8(98, 4), C8(99, 4), C8(100, 4), C8(101, 4), + C8(102, 4), C8(103, 4), C8(104, 4), C8(105, 4), C8(106, 4), C8(107, 4), + C8(108, 4), C8(109, 4), C8(110, 4), C8(111, 4), C8(112, 4), C8(113, 4), + C8(114, 4), C8(115, 4), C8(116, 4), C8(117, 4), C8(118, 4), C8(119, 4), + C8(120, 4), C8(121, 4), C8(122, 4), C8(123, 4), C8(124, 4), C8(125, 4), + C8(126, 4), C8(127, 4), C8(128, 4), C8(129, 4), C8(130, 4), C8(131, 4), + C8(132, 4), C8(133, 4), C8(134, 4), C8(135, 4), C8(136, 4), C8(137, 4), + C8(138, 4), C8(139, 4), C8(140, 4), C8(141, 4), C8(142, 4), C8(143, 4), + C8(144, 4), C8(145, 4), C8(146, 4), C8(147, 4), C8(148, 4), C8(149, 4), + C8(150, 4), C8(151, 4), C8(152, 4), C8(153, 4), C8(154, 4), C8(155, 4), + C8(156, 4), C8(157, 4), C8(158, 4), C8(159, 4), C8(160, 4), C8(161, 4), + C8(162, 4), C8(163, 4), C8(164, 4), C8(165, 4), C8(166, 4), C8(167, 4), + C8(168, 4), C8(169, 4), C8(170, 4), C8(171, 4), C8(172, 4), C8(173, 4), + C8(174, 4), C8(175, 4), C8(176, 4), C8(177, 4), C8(178, 4), C8(179, 4), + C8(180, 4), C8(181, 4), C8(182, 4), C8(183, 4), C8(184, 4), C8(185, 4), + C8(186, 4), C8(187, 4), C8(188, 4), C8(189, 4), C8(190, 4), C8(191, 4), + C8(192, 4), C8(193, 4), C8(194, 4), C8(195, 4), C8(196, 4), C8(197, 4), + C8(198, 4), C8(199, 4), C8(200, 4), C8(201, 4), C8(202, 4), C8(203, 4), + C8(204, 4), C8(205, 4), C8(206, 4), C8(207, 4), C8(208, 4), C8(209, 4), + C8(210, 4), C8(211, 4), C8(212, 4), C8(213, 4), C8(214, 4), C8(215, 4), + C8(216, 4), C8(217, 4), C8(218, 4), C8(219, 4), C8(220, 4), C8(221, 4), + C8(222, 4), C8(223, 4), C8(224, 4), C8(225, 4), C8(226, 4), C8(227, 4), + C8(228, 4), C8(229, 4), C8(230, 4), C8(231, 4), C8(232, 4), C8(233, 4), + C8(234, 4), C8(235, 4), C8(236, 4), C8(237, 4), C8(238, 4), C8(239, 4), + C8(240, 4), C8(241, 4), C8(242, 4), C8(243, 4), C8(244, 4), C8(245, 4), + C8(246, 4), C8(247, 4), C8(248, 4), C8(249, 4), C8(250, 4), C8(251, 4), + C8(252, 4), C8(253, 4), C8(254, 4), C8(255, 4), +}; + +const FbBits fbStipple4Bits[16] = { + C4(0, 8), C4(1, 8), C4(2, 8), C4(3, 8), C4(4, 8), C4(5, 8), + C4(6, 8), C4(7, 8), C4(8, 8), C4(9, 8), C4(10, 8), C4(11, 8), + C4(12, 8), C4(13, 8), C4(14, 8), C4(15, 8), +}; + +const FbBits fbStipple2Bits[4] = { + C2(0, 16), C2(1, 16), C2(2, 16), C2(3, 16), +}; + +const FbBits fbStipple1Bits[2] = { + C1(0, 32), C1(1, 32), +}; +#endif +#if FB_UNIT == 64 +const FbBits fbStipple16Bits[256] = { + C8(0, 4), C8(1, 4), C8(2, 4), C8(3, 4), C8(4, 4), C8(5, 4), + C8(6, 4), C8(7, 4), C8(8, 4), C8(9, 4), C8(10, 4), C8(11, 4), + C8(12, 4), C8(13, 4), C8(14, 4), C8(15, 4), C8(16, 4), C8(17, 4), + C8(18, 4), C8(19, 4), C8(20, 4), C8(21, 4), C8(22, 4), C8(23, 4), + C8(24, 4), C8(25, 4), C8(26, 4), C8(27, 4), C8(28, 4), C8(29, 4), + C8(30, 4), C8(31, 4), C8(32, 4), C8(33, 4), C8(34, 4), C8(35, 4), + C8(36, 4), C8(37, 4), C8(38, 4), C8(39, 4), C8(40, 4), C8(41, 4), + C8(42, 4), C8(43, 4), C8(44, 4), C8(45, 4), C8(46, 4), C8(47, 4), + C8(48, 4), C8(49, 4), C8(50, 4), C8(51, 4), C8(52, 4), C8(53, 4), + C8(54, 4), C8(55, 4), C8(56, 4), C8(57, 4), C8(58, 4), C8(59, 4), + C8(60, 4), C8(61, 4), C8(62, 4), C8(63, 4), C8(64, 4), C8(65, 4), + C8(66, 4), C8(67, 4), C8(68, 4), C8(69, 4), C8(70, 4), C8(71, 4), + C8(72, 4), C8(73, 4), C8(74, 4), C8(75, 4), C8(76, 4), C8(77, 4), + C8(78, 4), C8(79, 4), C8(80, 4), C8(81, 4), C8(82, 4), C8(83, 4), + C8(84, 4), C8(85, 4), C8(86, 4), C8(87, 4), C8(88, 4), C8(89, 4), + C8(90, 4), C8(91, 4), C8(92, 4), C8(93, 4), C8(94, 4), C8(95, 4), + C8(96, 4), C8(97, 4), C8(98, 4), C8(99, 4), C8(100, 4), C8(101, 4), + C8(102, 4), C8(103, 4), C8(104, 4), C8(105, 4), C8(106, 4), C8(107, 4), + C8(108, 4), C8(109, 4), C8(110, 4), C8(111, 4), C8(112, 4), C8(113, 4), + C8(114, 4), C8(115, 4), C8(116, 4), C8(117, 4), C8(118, 4), C8(119, 4), + C8(120, 4), C8(121, 4), C8(122, 4), C8(123, 4), C8(124, 4), C8(125, 4), + C8(126, 4), C8(127, 4), C8(128, 4), C8(129, 4), C8(130, 4), C8(131, 4), + C8(132, 4), C8(133, 4), C8(134, 4), C8(135, 4), C8(136, 4), C8(137, 4), + C8(138, 4), C8(139, 4), C8(140, 4), C8(141, 4), C8(142, 4), C8(143, 4), + C8(144, 4), C8(145, 4), C8(146, 4), C8(147, 4), C8(148, 4), C8(149, 4), + C8(150, 4), C8(151, 4), C8(152, 4), C8(153, 4), C8(154, 4), C8(155, 4), + C8(156, 4), C8(157, 4), C8(158, 4), C8(159, 4), C8(160, 4), C8(161, 4), + C8(162, 4), C8(163, 4), C8(164, 4), C8(165, 4), C8(166, 4), C8(167, 4), + C8(168, 4), C8(169, 4), C8(170, 4), C8(171, 4), C8(172, 4), C8(173, 4), + C8(174, 4), C8(175, 4), C8(176, 4), C8(177, 4), C8(178, 4), C8(179, 4), + C8(180, 4), C8(181, 4), C8(182, 4), C8(183, 4), C8(184, 4), C8(185, 4), + C8(186, 4), C8(187, 4), C8(188, 4), C8(189, 4), C8(190, 4), C8(191, 4), + C8(192, 4), C8(193, 4), C8(194, 4), C8(195, 4), C8(196, 4), C8(197, 4), + C8(198, 4), C8(199, 4), C8(200, 4), C8(201, 4), C8(202, 4), C8(203, 4), + C8(204, 4), C8(205, 4), C8(206, 4), C8(207, 4), C8(208, 4), C8(209, 4), + C8(210, 4), C8(211, 4), C8(212, 4), C8(213, 4), C8(214, 4), C8(215, 4), + C8(216, 4), C8(217, 4), C8(218, 4), C8(219, 4), C8(220, 4), C8(221, 4), + C8(222, 4), C8(223, 4), C8(224, 4), C8(225, 4), C8(226, 4), C8(227, 4), + C8(228, 4), C8(229, 4), C8(230, 4), C8(231, 4), C8(232, 4), C8(233, 4), + C8(234, 4), C8(235, 4), C8(236, 4), C8(237, 4), C8(238, 4), C8(239, 4), + C8(240, 4), C8(241, 4), C8(242, 4), C8(243, 4), C8(244, 4), C8(245, 4), + C8(246, 4), C8(247, 4), C8(248, 4), C8(249, 4), C8(250, 4), C8(251, 4), + C8(252, 4), C8(253, 4), C8(254, 4), C8(255, 4), +}; + +const FbBits fbStipple8Bits[256] = { + C8(0, 8), C8(1, 8), C8(2, 8), C8(3, 8), C8(4, 8), C8(5, 8), + C8(6, 8), C8(7, 8), C8(8, 8), C8(9, 8), C8(10, 8), C8(11, 8), + C8(12, 8), C8(13, 8), C8(14, 8), C8(15, 8), C8(16, 8), C8(17, 8), + C8(18, 8), C8(19, 8), C8(20, 8), C8(21, 8), C8(22, 8), C8(23, 8), + C8(24, 8), C8(25, 8), C8(26, 8), C8(27, 8), C8(28, 8), C8(29, 8), + C8(30, 8), C8(31, 8), C8(32, 8), C8(33, 8), C8(34, 8), C8(35, 8), + C8(36, 8), C8(37, 8), C8(38, 8), C8(39, 8), C8(40, 8), C8(41, 8), + C8(42, 8), C8(43, 8), C8(44, 8), C8(45, 8), C8(46, 8), C8(47, 8), + C8(48, 8), C8(49, 8), C8(50, 8), C8(51, 8), C8(52, 8), C8(53, 8), + C8(54, 8), C8(55, 8), C8(56, 8), C8(57, 8), C8(58, 8), C8(59, 8), + C8(60, 8), C8(61, 8), C8(62, 8), C8(63, 8), C8(64, 8), C8(65, 8), + C8(66, 8), C8(67, 8), C8(68, 8), C8(69, 8), C8(70, 8), C8(71, 8), + C8(72, 8), C8(73, 8), C8(74, 8), C8(75, 8), C8(76, 8), C8(77, 8), + C8(78, 8), C8(79, 8), C8(80, 8), C8(81, 8), C8(82, 8), C8(83, 8), + C8(84, 8), C8(85, 8), C8(86, 8), C8(87, 8), C8(88, 8), C8(89, 8), + C8(90, 8), C8(91, 8), C8(92, 8), C8(93, 8), C8(94, 8), C8(95, 8), + C8(96, 8), C8(97, 8), C8(98, 8), C8(99, 8), C8(100, 8), C8(101, 8), + C8(102, 8), C8(103, 8), C8(104, 8), C8(105, 8), C8(106, 8), C8(107, 8), + C8(108, 8), C8(109, 8), C8(110, 8), C8(111, 8), C8(112, 8), C8(113, 8), + C8(114, 8), C8(115, 8), C8(116, 8), C8(117, 8), C8(118, 8), C8(119, 8), + C8(120, 8), C8(121, 8), C8(122, 8), C8(123, 8), C8(124, 8), C8(125, 8), + C8(126, 8), C8(127, 8), C8(128, 8), C8(129, 8), C8(130, 8), C8(131, 8), + C8(132, 8), C8(133, 8), C8(134, 8), C8(135, 8), C8(136, 8), C8(137, 8), + C8(138, 8), C8(139, 8), C8(140, 8), C8(141, 8), C8(142, 8), C8(143, 8), + C8(144, 8), C8(145, 8), C8(146, 8), C8(147, 8), C8(148, 8), C8(149, 8), + C8(150, 8), C8(151, 8), C8(152, 8), C8(153, 8), C8(154, 8), C8(155, 8), + C8(156, 8), C8(157, 8), C8(158, 8), C8(159, 8), C8(160, 8), C8(161, 8), + C8(162, 8), C8(163, 8), C8(164, 8), C8(165, 8), C8(166, 8), C8(167, 8), + C8(168, 8), C8(169, 8), C8(170, 8), C8(171, 8), C8(172, 8), C8(173, 8), + C8(174, 8), C8(175, 8), C8(176, 8), C8(177, 8), C8(178, 8), C8(179, 8), + C8(180, 8), C8(181, 8), C8(182, 8), C8(183, 8), C8(184, 8), C8(185, 8), + C8(186, 8), C8(187, 8), C8(188, 8), C8(189, 8), C8(190, 8), C8(191, 8), + C8(192, 8), C8(193, 8), C8(194, 8), C8(195, 8), C8(196, 8), C8(197, 8), + C8(198, 8), C8(199, 8), C8(200, 8), C8(201, 8), C8(202, 8), C8(203, 8), + C8(204, 8), C8(205, 8), C8(206, 8), C8(207, 8), C8(208, 8), C8(209, 8), + C8(210, 8), C8(211, 8), C8(212, 8), C8(213, 8), C8(214, 8), C8(215, 8), + C8(216, 8), C8(217, 8), C8(218, 8), C8(219, 8), C8(220, 8), C8(221, 8), + C8(222, 8), C8(223, 8), C8(224, 8), C8(225, 8), C8(226, 8), C8(227, 8), + C8(228, 8), C8(229, 8), C8(230, 8), C8(231, 8), C8(232, 8), C8(233, 8), + C8(234, 8), C8(235, 8), C8(236, 8), C8(237, 8), C8(238, 8), C8(239, 8), + C8(240, 8), C8(241, 8), C8(242, 8), C8(243, 8), C8(244, 8), C8(245, 8), + C8(246, 8), C8(247, 8), C8(248, 8), C8(249, 8), C8(250, 8), C8(251, 8), + C8(252, 8), C8(253, 8), C8(254, 8), C8(255, 8), +}; + +const FbBits fbStipple4Bits[16] = { + C4(0, 16), C4(1, 16), C4(2, 16), C4(3, 16), C4(4, 16), C4(5, 16), + C4(6, 16), C4(7, 16), C4(8, 16), C4(9, 16), C4(10, 16), C4(11, 16), + C4(12, 16), C4(13, 16), C4(14, 16), C4(15, 16), +}; + +const FbBits fbStipple2Bits[4] = { + C2(0, 32), C2(1, 32), C2(2, 32), C2(3, 32), +}; + +#define fbStipple1Bits 0 +#endif +const FbBits *const fbStippleTable[] = { + 0, + fbStipple1Bits, + fbStipple2Bits, + 0, + fbStipple4Bits, + 0, + 0, + 0, + fbStipple8Bits, +}; diff --git a/fb/fbwindow.c b/fb/fbwindow.c new file mode 100644 index 0000000..d687481 --- /dev/null +++ b/fb/fbwindow.c @@ -0,0 +1,314 @@ +/* + * + * Copyright © 1998 Keith Packard + * + * 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, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include + +#include "fb.h" + + +Bool +fbCreateWindow(WindowPtr pWin) +{ + pWin->devPrivates[fbWinPrivateIndex].ptr = + (pointer) fbGetScreenPixmap(pWin->drawable.pScreen); + if (pWin->drawable.bitsPerPixel == 32) + pWin->drawable.bitsPerPixel = + fbGetScreenPrivate(pWin->drawable.pScreen)->win32bpp; + return TRUE; +} + +Bool +fbDestroyWindow(WindowPtr pWin) +{ + return TRUE; +} + +Bool +fbMapWindow(WindowPtr pWindow) +{ + return TRUE; +} + +Bool +fbPositionWindow(WindowPtr pWin, int x, int y) +{ + return TRUE; +} + +Bool +fbUnmapWindow(WindowPtr pWindow) +{ + return TRUE; +} + +void +fbCopyWindowProc(DrawablePtr pSrcDrawable, + DrawablePtr pDstDrawable, + GCPtr pGC, + BoxPtr pbox, + int nbox, + int dx, + int dy, + Bool reverse, Bool upsidedown, Pixel bitplane, void *closure) +{ + FbBits *src; + + FbStride srcStride; + + int srcBpp; + + int srcXoff, srcYoff; + + FbBits *dst; + + FbStride dstStride; + + int dstBpp; + + int dstXoff, dstYoff; + + fbGetDrawable(pSrcDrawable, src, srcStride, srcBpp, srcXoff, srcYoff); + fbGetDrawable(pDstDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); + + while (nbox--) { + fbBlt(src + (pbox->y1 + dy + srcYoff) * srcStride, + srcStride, + (pbox->x1 + dx + srcXoff) * srcBpp, + dst + (pbox->y1 + dstYoff) * dstStride, + dstStride, + (pbox->x1 + dstXoff) * dstBpp, + (pbox->x2 - pbox->x1) * dstBpp, + (pbox->y2 - pbox->y1), + GXcopy, FB_ALLONES, dstBpp, reverse, upsidedown); + pbox++; + } +} + +void +fbCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc) +{ + RegionRec rgnDst; + + int dx, dy; + + PixmapPtr pPixmap = fbGetWindowPixmap(pWin); + + DrawablePtr pDrawable = &pPixmap->drawable; + + dx = ptOldOrg.x - pWin->drawable.x; + dy = ptOldOrg.y - pWin->drawable.y; + REGION_TRANSLATE(prgnSrc, -dx, -dy); + + REGION_NULL(&rgnDst); + + REGION_INTERSECT(&rgnDst, &pWin->borderClip, + prgnSrc); + + + fbCopyRegion(pDrawable, pDrawable, + 0, &rgnDst, dx, dy, fbCopyWindowProc, 0, 0); + + REGION_UNINIT(&rgnDst); + fbValidateDrawable(&pWin->drawable); +} + +Bool +fbChangeWindowAttributes(WindowPtr pWin, unsigned long mask) +{ + PixmapPtr pPixmap; + + if (mask & CWBackPixmap) { + if (pWin->backgroundState == BackgroundPixmap) { + pPixmap = pWin->background.pixmap; + if (pPixmap->drawable.bitsPerPixel != pWin->drawable.bitsPerPixel) { + pPixmap = fb24_32ReformatTile(pPixmap, + pWin->drawable.bitsPerPixel); + if (pPixmap) { + (*pWin->drawable.pScreen->DestroyPixmap) (pWin->background. + pixmap); + pWin->background.pixmap = pPixmap; + } + } + if (FbEvenTile(pPixmap->drawable.width * + pPixmap->drawable.bitsPerPixel)) + fbPadPixmap(pPixmap); + } + } + if (mask & CWBorderPixmap) { + if (pWin->borderIsPixel == FALSE) { + pPixmap = pWin->border.pixmap; + if (pPixmap->drawable.bitsPerPixel != pWin->drawable.bitsPerPixel) { + pPixmap = fb24_32ReformatTile(pPixmap, + pWin->drawable.bitsPerPixel); + if (pPixmap) { + (*pWin->drawable.pScreen->DestroyPixmap) (pWin->border. + pixmap); + pWin->border.pixmap = pPixmap; + } + } + if (FbEvenTile(pPixmap->drawable.width * + pPixmap->drawable.bitsPerPixel)) + fbPadPixmap(pPixmap); + } + } + return TRUE; +} + +void +fbFillRegionSolid(DrawablePtr pDrawable, + RegionPtr pRegion, FbBits and, FbBits xor) +{ + FbBits *dst; + + FbStride dstStride; + + int dstBpp; + + int dstXoff, dstYoff; + + int n = REGION_NUM_RECTS(pRegion); + + BoxPtr pbox = REGION_RECTS(pRegion); + + + fbGetDrawable(pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); + + while (n--) { + fbSolid(dst + (pbox->y1 + dstYoff) * dstStride, + dstStride, + (pbox->x1 + dstXoff) * dstBpp, + dstBpp, + (pbox->x2 - pbox->x1) * dstBpp, + pbox->y2 - pbox->y1, and, xor); + fbValidateDrawable(pDrawable); + pbox++; + } +} + + +void +fbFillRegionTiled(DrawablePtr pDrawable, RegionPtr pRegion, PixmapPtr pTile) +{ + FbBits *dst; + + FbStride dstStride; + + int dstBpp; + + int dstXoff, dstYoff; + + FbBits *tile; + + FbStride tileStride; + + int tileBpp; + + int tileXoff _X_UNUSED, tileYoff _X_UNUSED; /* XXX assumed to be zero */ + + int tileWidth, tileHeight; + + int n = REGION_NUM_RECTS(pRegion); + + BoxPtr pbox = REGION_RECTS(pRegion); + + int xRot = pDrawable->x; + + int yRot = pDrawable->y; + + fbGetDrawable(pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); + fbGetDrawable(&pTile->drawable, tile, tileStride, tileBpp, tileXoff, + tileYoff); + tileWidth = pTile->drawable.width; + tileHeight = pTile->drawable.height; + xRot += dstXoff; + yRot += dstYoff; + + while (n--) { + fbTile(dst + (pbox->y1 + dstYoff) * dstStride, + dstStride, + (pbox->x1 + dstXoff) * dstBpp, + (pbox->x2 - pbox->x1) * dstBpp, + pbox->y2 - pbox->y1, + tile, + tileStride, + tileWidth * dstBpp, + tileHeight, + GXcopy, + FB_ALLONES, dstBpp, xRot * dstBpp, yRot - (pbox->y1 + dstYoff)); + pbox++; + } +} + +void +fbPaintWindow(WindowPtr pWin, RegionPtr pRegion, int what) +{ + WindowPtr pBgWin; + + switch (what) { + case PW_BACKGROUND: + switch (pWin->backgroundState) { + case None: + break; + case ParentRelative: + do { + pWin = pWin->parent; + } while (pWin->backgroundState == ParentRelative); + (*pWin->drawable.pScreen->PaintWindowBackground) (pWin, pRegion, + what); + break; + case BackgroundPixmap: + fbFillRegionTiled(&pWin->drawable, + pRegion, pWin->background.pixmap); + break; + case BackgroundPixel: + fbFillRegionSolid(&pWin->drawable, + pRegion, + 0, + fbReplicatePixel(pWin->background.pixel, + pWin->drawable.bitsPerPixel)); + break; + } + break; + case PW_BORDER: + if (pWin->borderIsPixel) { + fbFillRegionSolid(&pWin->drawable, + pRegion, + 0, + fbReplicatePixel(pWin->border.pixel, + pWin->drawable.bitsPerPixel)); + } + else { + for (pBgWin = pWin; + pBgWin->backgroundState == ParentRelative; + pBgWin = pBgWin->parent); + + fbFillRegionTiled(&pBgWin->drawable, pRegion, pWin->border.pixmap); + } + break; + } + fbValidateDrawable(&pWin->drawable); +} diff --git a/include/Makefile.am b/include/Makefile.am new file mode 100644 index 0000000..6e5d7d6 --- /dev/null +++ b/include/Makefile.am @@ -0,0 +1,12 @@ +AM_CFLAGS = $(DIX_CFLAGS) + +EXTRA_DIST = do-not-use-config.h dix-config.h \ + closestr.h closure.h colormap.h colormapst.h cursor.h cursorstr.h \ + dix-config.h dix-config.h.in dixevents.h dixfont.h dixfontstr.h dixgrabs.h \ + dix.h dixstruct.h do-not-use-config.h do-not-use-config.h.in exevents.h \ + extension.h extinit.h extnsionst.h gc.h gcstruct.h globals.h input.h \ + inputstr.h kdrive-config.h kdrive-config.h.in Makefile Makefile.am \ + Makefile.in misc.h misc.h.orig miscstruct.h opaque.h os.h pixmap.h \ + pixmapstr.h property.h propertyst.h region.h regionstr.h resource.h \ + screenint.h scrnintstr.h selection.h servermd.h site.h stamp-h1 stamp-h2 \ + stamp-h3 swaprep.h swapreq.h validate.h window.h windowstr.h diff --git a/include/closestr.h b/include/closestr.h new file mode 100644 index 0000000..2cd67b1 --- /dev/null +++ b/include/closestr.h @@ -0,0 +1,156 @@ +/* + +Copyright 1991, 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. + +*/ + + +#ifndef CLOSESTR_H +#define CLOSESTR_H + +#include +#include "closure.h" +#include "dix.h" +#include "misc.h" +#include "gcstruct.h" + +/* closure structures */ + +/* OpenFont */ + +typedef struct _OFclosure { + ClientPtr client; + short current_fpe; + short num_fpes; + FontPathElementPtr *fpe_list; + Mask flags; + Bool slept; + +/* XXX -- get these from request buffer instead? */ + char *origFontName; + int origFontNameLen; + XID fontid; + char *fontname; + int fnamelen; + FontPtr non_cachable_font; +} OFclosureRec; + +/* ListFontsWithInfo */ + +#define XLFDMAXFONTNAMELEN 256 +typedef struct _LFWIstate { + char pattern[XLFDMAXFONTNAMELEN]; + int patlen; + int current_fpe; + int max_names; + Bool list_started; + pointer private; +} LFWIstateRec, *LFWIstatePtr; + +typedef struct _LFWIclosure { + ClientPtr client; + int num_fpes; + FontPathElementPtr *fpe_list; + xListFontsWithInfoReply *reply; + int length; + LFWIstateRec current; + LFWIstateRec saved; + int savedNumFonts; + Bool haveSaved; + Bool slept; + char *savedName; +} LFWIclosureRec; + +/* ListFonts */ + +typedef struct _LFclosure { + ClientPtr client; + int num_fpes; + FontPathElementPtr *fpe_list; + FontNamesPtr names; + LFWIstateRec current; + LFWIstateRec saved; + Bool haveSaved; + Bool slept; + char *savedName; + int savedNameLen; +} LFclosureRec; + +/* PolyText */ + +typedef + int (* PolyTextPtr)( + DrawablePtr /* pDraw */, + GCPtr /* pGC */, + int /* x */, + int /* y */, + int /* count */, + void * /* chars or shorts */ + ); + +typedef struct _PTclosure { + ClientPtr client; + DrawablePtr pDraw; + GC *pGC; + unsigned char *pElt; + unsigned char *endReq; + unsigned char *data; + int xorg; + int yorg; + CARD8 reqType; + PolyTextPtr polyText; + int itemSize; + XID did; + int err; + Bool slept; +} PTclosureRec; + +/* ImageText */ + +typedef + void (* ImageTextPtr)( + DrawablePtr /* pDraw */, + GCPtr /* pGC */, + int /* x */, + int /* y */, + int /* count */, + void * /* chars or shorts */ + ); + +typedef struct _ITclosure { + ClientPtr client; + DrawablePtr pDraw; + GC *pGC; + BYTE nChars; + unsigned char *data; + int xorg; + int yorg; + CARD8 reqType; + ImageTextPtr imageText; + int itemSize; + XID did; + Bool slept; +} ITclosureRec; +#endif /* CLOSESTR_H */ diff --git a/include/closure.h b/include/closure.h new file mode 100644 index 0000000..b9534c5 --- /dev/null +++ b/include/closure.h @@ -0,0 +1,57 @@ +/*********************************************************** + +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. + +******************************************************************/ + +#ifndef CLOSURE_H +#define CLOSURE_H 1 + +typedef struct _LFclosure *LFclosurePtr; +typedef struct _LFWIclosure *LFWIclosurePtr; +typedef struct _OFclosure *OFclosurePtr; +typedef struct _PTclosure *PTclosurePtr; +typedef struct _ITclosure *ITclosurePtr; + +#endif /* CLOSURE_H */ diff --git a/include/colormap.h b/include/colormap.h new file mode 100644 index 0000000..e3d7836 --- /dev/null +++ b/include/colormap.h @@ -0,0 +1,182 @@ +/* + +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. + +*/ + +#ifndef CMAP_H +#define CMAP_H 1 + +#include +#include "screenint.h" +#include "window.h" + +/* these follow X.h's AllocNone and AllocAll */ +#define CM_PSCREEN 2 +#define CM_PWIN 3 +/* Passed internally in colormap.c */ +#define REDMAP 0 +#define GREENMAP 1 +#define BLUEMAP 2 +#define PSEUDOMAP 3 +#define AllocPrivate (-1) +#define AllocTemporary (-2) +#define DynamicClass 1 + +/* Values for the flags field of a colormap. These should have 1 bit set + * and not overlap */ +#define IsDefault 1 +#define AllAllocated 2 +#define BeingCreated 4 + + +typedef CARD32 Pixel; +typedef struct _CMEntry *EntryPtr; +/* moved to screenint.h: typedef struct _ColormapRec *ColormapPtr */ +typedef struct _colorResource *colorResourcePtr; + +int CreateColormap( + Colormap /*mid*/, + ScreenPtr /*pScreen*/, + VisualPtr /*pVisual*/, + ColormapPtr* /*ppcmap*/, + int /*alloc*/, + int /*client*/); + +int FreeColormap( + pointer /*pmap*/, + XID /*mid*/); + +int TellLostMap( + WindowPtr /*pwin*/, + pointer /* Colormap *pmid */); + +int TellGainedMap( + WindowPtr /*pwin*/, + pointer /* Colormap *pmid */); + +int CopyColormapAndFree( + Colormap /*mid*/, + ColormapPtr /*pSrc*/, + int /*client*/); + +int AllocColor( + ColormapPtr /*pmap*/, + unsigned short* /*pred*/, + unsigned short* /*pgreen*/, + unsigned short* /*pblue*/, + Pixel* /*pPix*/, + int /*client*/); + +void FakeAllocColor( + ColormapPtr /*pmap*/, + xColorItem * /*item*/); + +void FakeFreeColor( + ColormapPtr /*pmap*/, + Pixel /*pixel*/); + +typedef int (*ColorCompareProcPtr)( + EntryPtr /*pent*/, + xrgb * /*prgb*/); + +int FindColor( + ColormapPtr /*pmap*/, + EntryPtr /*pentFirst*/, + int /*size*/, + xrgb* /*prgb*/, + Pixel* /*pPixel*/, + int /*channel*/, + int /*client*/, + ColorCompareProcPtr /*comp*/); + +int QueryColors( + ColormapPtr /*pmap*/, + int /*count*/, + Pixel* /*ppixIn*/, + xrgb* /*prgbList*/); + +int FreeClientPixels( + pointer /*pcr*/, + XID /*fakeid*/); + +int AllocColorCells( + int /*client*/, + ColormapPtr /*pmap*/, + int /*colors*/, + int /*planes*/, + Bool /*contig*/, + Pixel* /*ppix*/, + Pixel* /*masks*/); + +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 FreeColors( + ColormapPtr /*pmap*/, + int /*client*/, + int /*count*/, + Pixel* /*pixels*/, + Pixel /*mask*/); + +int StoreColors( + ColormapPtr /*pmap*/, + int /*count*/, + xColorItem* /*defs*/); + +int IsMapInstalled( + Colormap /*map*/, + WindowPtr /*pWin*/); + +#endif /* CMAP_H */ diff --git a/include/colormapst.h b/include/colormapst.h new file mode 100644 index 0000000..b866b59 --- /dev/null +++ b/include/colormapst.h @@ -0,0 +1,133 @@ +/* + +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. + +*/ + +#ifndef CMAPSTRUCT_H +#define CMAPSTRUCT_H 1 + +#include + +#include "colormap.h" +#include "screenint.h" + +/* Shared color -- the color is used by AllocColorPlanes */ +typedef struct +{ + unsigned short color; + short refcnt; +} SHAREDCOLOR; + +/* LOCO -- a local color for a PseudoColor cell. DirectColor maps always + * use the first value (called red) in the structure. What channel they + * are really talking about depends on which map they are in. */ +typedef struct +{ + unsigned short red, green, blue; +} LOCO; + +/* SHCO -- a shared color for a PseudoColor cell. Used with AllocColorPlanes. + * DirectColor maps always use the first value (called red) in the structure. + * What channel they are really talking about depends on which map they + * are in. */ +typedef struct +{ + SHAREDCOLOR *red, *green, *blue; +} SHCO; + + +/* color map entry */ +typedef struct _CMEntry +{ + union + { + LOCO local; + SHCO shco; + } co; + short refcnt; + Bool fShared; +} Entry; + +/* + * COLORMAPs can be used for either Direct or Pseudo color. PseudoColor + * only needs one cell table, we arbitrarily pick red. We keep track + * of that table with freeRed, numPixelsRed, and clientPixelsRed + * + * The padN variables are unfortunate ABI BC. See fdo bug #6924. + */ + +typedef struct _ColormapRec +{ + VisualPtr pVisual; + short class; /* PseudoColor or DirectColor */ +#if defined(_XSERVER64) + short pad0; + XID pad1; +#endif + XID mid; /* client's name for colormap */ +#if defined(_XSERVER64) && (X_BYTE_ORDER == X_LITTLE_ENDIAN) + XID pad2; +#endif + ScreenPtr pScreen; /* screen map is associated with */ + short flags; /* 1 = IsDefault + * 2 = AllAllocated */ + int freeRed; + int freeGreen; + int freeBlue; + int *numPixelsRed; + int *numPixelsGreen; + int *numPixelsBlue; + Pixel **clientPixelsRed; + Pixel **clientPixelsGreen; + Pixel **clientPixelsBlue; + Entry *red; + Entry *green; + Entry *blue; + pointer devPriv; + DevUnion *devPrivates; /* dynamic devPrivates added after devPriv + already existed - must keep devPriv */ +} ColormapRec; + +#endif /* COLORMAP_H */ diff --git a/include/cursor.h b/include/cursor.h new file mode 100644 index 0000000..33a9df9 --- /dev/null +++ b/include/cursor.h @@ -0,0 +1,138 @@ +/*********************************************************** + +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. + +******************************************************************/ + +#ifndef CURSOR_H +#define CURSOR_H + +#include "misc.h" +#include "screenint.h" +#include "window.h" + +#define NullCursor ((CursorPtr)NULL) + +/* Provide support for alpha composited cursors */ +#define ARGB_CURSOR + +typedef struct _Cursor *CursorPtr; +typedef struct _CursorMetric *CursorMetricPtr; + +extern CursorPtr rootCursor; + +int FreeCursor( + pointer /*pCurs*/, + XID /*cid*/); + +/* Quartz support on Mac OS X pulls in the QuickDraw + framework whose AllocCursor function conflicts here. */ +CursorPtr AllocCursor( + unsigned char* /*psrcbits*/, + unsigned char* /*pmaskbits*/, + CursorMetricPtr /*cm*/, + unsigned /*foreRed*/, + unsigned /*foreGreen*/, + unsigned /*foreBlue*/, + unsigned /*backRed*/, + unsigned /*backGreen*/, + unsigned /*backBlue*/); + +CursorPtr AllocCursorARGB( + unsigned char* /*psrcbits*/, + unsigned char* /*pmaskbits*/, + CARD32* /*argb*/, + CursorMetricPtr /*cm*/, + unsigned /*foreRed*/, + unsigned /*foreGreen*/, + unsigned /*foreBlue*/, + unsigned /*backRed*/, + unsigned /*backGreen*/, + unsigned /*backBlue*/); + +int AllocGlyphCursor( + Font /*source*/, + unsigned int /*sourceChar*/, + Font /*mask*/, + unsigned int /*maskChar*/, + unsigned /*foreRed*/, + unsigned /*foreGreen*/, + unsigned /*foreBlue*/, + unsigned /*backRed*/, + unsigned /*backGreen*/, + unsigned /*backBlue*/, + CursorPtr* /*ppCurs*/, + ClientPtr /*client*/); + +CursorPtr CreateRootCursor( + char* /*pfilename*/, + unsigned int /*glyph*/); + +int ServerBitsFromGlyph( + FontPtr /*pfont*/, + unsigned int /*ch*/, + register CursorMetricPtr /*cm*/, + unsigned char ** /*ppbits*/); + +Bool CursorMetricsFromGlyph( + FontPtr /*pfont*/, + unsigned /*ch*/, + CursorMetricPtr /*cm*/); + +void CheckCursorConfinement( + WindowPtr /*pWin*/); + +void NewCurrentScreen( + ScreenPtr /*newScreen*/, + int /*x*/, + int /*y*/); + +Bool PointerConfinedToScreen(void); + +void GetSpritePosition( + int * /*px*/, + int * /*py*/); + + +#endif /* CURSOR_H */ diff --git a/include/cursorstr.h b/include/cursorstr.h new file mode 100644 index 0000000..782428f --- /dev/null +++ b/include/cursorstr.h @@ -0,0 +1,91 @@ +/*********************************************************** + +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. + +******************************************************************/ + +#ifndef CURSORSTRUCT_H +#define CURSORSTRUCT_H + +#include "cursor.h" +/* + * device-independent cursor storage + */ + +/* + * source and mask point directly to the bits, which are in the server-defined + * bitmap format. + */ +typedef struct _CursorBits { + unsigned char *source; /* points to bits */ + unsigned char *mask; /* points to bits */ + Bool emptyMask; /* all zeros mask */ + unsigned short width, height, xhot, yhot; /* metrics */ + int refcnt; /* can be shared */ + pointer devPriv[MAXSCREENS]; /* set by pScr->RealizeCursor*/ +#ifdef ARGB_CURSOR + CARD32 *argb; /* full-color alpha blended */ +#endif +} CursorBits, *CursorBitsPtr; + +typedef struct _Cursor { + CursorBitsPtr bits; + unsigned short foreRed, foreGreen, foreBlue; /* device-independent color */ + unsigned short backRed, backGreen, backBlue; /* device-independent color */ + int refcnt; + pointer devPriv[MAXSCREENS]; /* set by pScr->RealizeCursor*/ + CARD32 serialNumber; + Atom name; +} CursorRec; + +typedef struct _CursorMetric { + unsigned short width, height, xhot, yhot; +} CursorMetricRec; + +typedef struct { + int x, y; + ScreenPtr pScreen; +} HotSpot; + +#endif /* CURSORSTRUCT_H */ diff --git a/include/dix-config.h.in b/include/dix-config.h.in new file mode 100644 index 0000000..24dc38e --- /dev/null +++ b/include/dix-config.h.in @@ -0,0 +1,257 @@ +/* dix-config.h.in: not at all generated. -*- c -*- */ + +#ifndef _DIX_CONFIG_H_ +#define _DIX_CONFIG_H_ + +/* Builder address */ +#undef BUILDERADDR + +/* Operating System Name */ +#undef OSNAME + +/* Default font path */ +#undef COMPILEDDEFAULTFONTPATH + +/* Define to 1 if using `alloca.c'. */ +#undef C_ALLOCA + +/* Build DPMS extension */ +#undef DPMSExtension + +/* Support XDM-AUTH*-1 */ +#undef HASXDMAUTH + +/* Define to 1 if you have the `getdtablesize' function. */ +#undef HAS_GETDTABLESIZE + +/* Define to 1 if you have the `getifaddrs' function. */ +#undef HAS_GETIFADDRS + +/* Define to 1 if you have the `getpeereid' function. */ +#undef HAS_GETPEEREID + +/* Define to 1 if you have the `getpeerucred' function. */ +#undef HAS_GETPEERUCRED + +/* Define to 1 if you have the `mmap' function. */ +#undef HAS_MMAP + +/* Define to 1 if you have `alloca', as a function or macro. */ +#undef HAVE_ALLOCA + +/* Define to 1 if you have and it should be used (not on Ultrix). + */ +#undef HAVE_ALLOCA_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_ASM_MTRR_H + +/* Define to 1 if you have the header file, and it defines `DIR'. */ +#undef HAVE_DIRENT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_DLFCN_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_FCNTL_H + +/* Define to 1 if you have the `geteuid' function. */ +#undef HAVE_GETEUID + +/* Define to 1 if you have the `getopt' function. */ +#undef HAVE_GETOPT + +/* Define to 1 if you have the `getopt_long' function. */ +#undef HAVE_GETOPT_LONG + +/* Define to 1 if you have the `getuid' function. */ +#undef HAVE_GETUID + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the `m' library (-lm). */ +#undef HAVE_LIBM + +/* Define to 1 if you have the `link' function. */ +#undef HAVE_LINK + +/* Define to 1 if you have the header file. */ +#undef HAVE_LINUX_APM_BIOS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LINUX_FB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LINUX_H3600_TS_H + +/* Define to 1 if you have the `memmove' function. */ +#undef HAVE_MEMMOVE + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the `memset' function. */ +#undef HAVE_MEMSET + +/* Define to 1 if you have the `mkstemp' function. */ +#undef HAVE_MKSTEMP + +/* Define to 1 if you have the header file, and it defines `DIR'. */ +#undef HAVE_NDIR_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the `strchr' function. */ +#undef HAVE_STRCHR + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the `strrchr' function. */ +#undef HAVE_STRRCHR + +/* Define to 1 if you have the `strtol' function. */ +#undef HAVE_STRTOL + +/* Define to 1 if SYSV IPC is available */ +#undef HAVE_SYSV_IPC + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_AGPIO_H + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#undef HAVE_SYS_DIR_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_IO_H + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#undef HAVE_SYS_NDIR_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_VM86_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define to 1 if you have the `vprintf' function. */ +#undef HAVE_VPRINTF + +/* Support IPv6 for TCP connections */ +#undef IPv6 + +/* Support os-specific local connections */ +#undef LOCALCONN + +/* Disable some debugging code */ +#undef NDEBUG + +/* Enable some debugging code */ +#undef DEBUG + +/* Name of package */ +#undef PACKAGE_STRING + +/* Overall prefix */ +#undef PROJECTROOT + +/* Support X resource extension */ +#undef RES + +/* Support MIT-SCREEN-SAVER extension */ +#undef SCREENSAVER + +/* Include time-based scheduler */ +#undef SMART_SCHEDULE + +/* If using the C implementation of alloca, define if you know the + direction of stack growth for your system; otherwise it will be + automatically deduced at run-time. + STACK_DIRECTION > 0 => grows toward higher addresses + STACK_DIRECTION < 0 => grows toward lower addresses + STACK_DIRECTION = 0 => direction of growth unknown */ +#undef STACK_DIRECTION + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Support TCP socket connections */ +#undef TCPCONN + +/* Support UNIX socket connections */ +#undef UNIXCONN + +/* unaligned word accesses behave as expected */ +#undef WORKING_UNALIGNED_INT + +/* Support Xdmcp */ +#undef XDMCP + +/* Build XFree86 BigFont extension */ +#undef XF86BIGFONT + +/* Vendor release */ +#undef XORG_RELEASE + +/* Current Xorg version */ +#undef XORG_VERSION_CURRENT + +/* Xorg release date */ +#undef XORG_DATE + +/* Build XRes extension */ +#undef XResExtension + +/* Build DBE support */ +#undef DBE + +/* Vendor name */ +#undef XVENDORNAME + +/* Endian order */ +#undef X_BYTE_ORDER + +/* Enable GNU and other extensions to the C environment for GLIBC */ +#undef _GNU_SOURCE + +/* Define to empty if `const' does not conform to ANSI C. */ +#undef const + +/* Define to `int' if does not define. */ +#undef pid_t + +/* Define to 1 if unsigned long is 64 bits. */ +#undef _XSERVER64 + +/* System is BSD-like */ +#undef CSRG_BASED + +/* Define to 1 if `struct sockaddr_in' has a `sin_len' member */ +#undef BSD44SOCKETS + +/* Have a monotonic clock from clock_gettime() */ +#undef MONOTONIC_CLOCK + +#if defined(__GNUC__) && !defined(_X_UNUSED) +#define _X_UNUSED __attribute__((unused)) +#else +#define _X_UNUSED +#endif + +#endif /* _DIX_CONFIG_H_ */ diff --git a/include/dix.h b/include/dix.h new file mode 100644 index 0000000..f31a9e6 --- /dev/null +++ b/include/dix.h @@ -0,0 +1,729 @@ +/*********************************************************** + +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. + +******************************************************************/ + +#ifndef DIX_H +#define DIX_H + +#include "gc.h" +#include "window.h" +#include "input.h" + +#define EARLIER -1 +#define SAMETIME 0 +#define LATER 1 + +#define NullClient ((ClientPtr) 0) +#define REQUEST(type) \ + register type *stuff = (type *)client->requestBuffer + + +#define REQUEST_SIZE_MATCH(req)\ + if ((sizeof(req) >> 2) != client->req_len)\ + return(BadLength) + +#define REQUEST_AT_LEAST_SIZE(req) \ + if ((sizeof(req) >> 2) > client->req_len )\ + return(BadLength) + +#define REQUEST_FIXED_SIZE(req, n)\ + if (((sizeof(req) >> 2) > client->req_len) || \ + (((sizeof(req) + (n) + 3) >> 2) != client->req_len)) \ + return(BadLength) + +#define LEGAL_NEW_RESOURCE(id,client)\ + if (!LegalNewID(id,client)) \ + {\ + client->errorValue = id;\ + return(BadIDChoice);\ + } + +/* XXX if you are using this macro, you are probably not generating Match + * errors where appropriate */ +#define LOOKUP_DRAWABLE(did, client)\ + ((client->lastDrawableID == did) ? \ + client->lastDrawable : (DrawablePtr)LookupDrawable(did, client)) + + +#define VERIFY_DRAWABLE(pDraw, did, client)\ + if (client->lastDrawableID == did)\ + pDraw = client->lastDrawable;\ + else \ + {\ + pDraw = (DrawablePtr) LookupIDByClass(did, RC_DRAWABLE);\ + if (!pDraw) \ + {\ + client->errorValue = did; \ + return BadDrawable;\ + }\ + if (pDraw->type == UNDRAWABLE_WINDOW)\ + return BadMatch;\ + } + +#define VERIFY_GEOMETRABLE(pDraw, did, client)\ + if (client->lastDrawableID == did)\ + pDraw = client->lastDrawable;\ + else \ + {\ + pDraw = (DrawablePtr) LookupIDByClass(did, RC_DRAWABLE);\ + if (!pDraw) \ + {\ + client->errorValue = did; \ + return BadDrawable;\ + }\ + } + +#define VERIFY_GC(pGC, rid, client)\ + if (client->lastGCID == rid)\ + pGC = client->lastGC;\ + else\ + pGC = (GC *)LookupIDByType(rid, RT_GC);\ + if (!pGC)\ + {\ + client->errorValue = rid;\ + return (BadGC);\ + } + +#define SECURITY_VERIFY_DRAWABLE(pDraw, did, client, mode)\ + VERIFY_DRAWABLE(pDraw, did, client) + +#define SECURITY_VERIFY_GEOMETRABLE(pDraw, did, client, mode)\ + VERIFY_GEOMETRABLE(pDraw, did, client) + +#define SECURITY_VERIFY_GC(pGC, rid, client, mode)\ + VERIFY_GC(pGC, rid, client) + + +/* + * We think that most hardware implementations of DBE will want + * LookupID*(dbe_back_buffer_id) to return the window structure that the + * id is a back buffer for. Since both front and back buffers will + * return the same structure, you need to be able to distinguish + * somewhere what kind of buffer (front/back) was being asked for, so + * that ddx can render to the right place. That's the problem that the + * following code solves. Note: we couldn't embed this in the LookupID* + * functions because the VALIDATE_DRAWABLE_AND_GC macro often circumvents + * those functions by checking a one-element cache. That's why we're + * mucking with VALIDATE_DRAWABLE_AND_GC. + * + * If you put -DNEED_DBE_BUF_BITS into PervasiveDBEDefines, the window + * structure will have two additional bits defined, srcBuffer and + * dstBuffer, and their values will be maintained via the macros + * SET_DBE_DSTBUF and SET_DBE_SRCBUF (below). If you also + * put -DNEED_DBE_BUF_VALIDATE into PervasiveDBEDefines, the function + * DbeValidateBuffer will be called any time the bits change to give you + * a chance to do some setup. See the DBE code for more details on this + * function. We put in these levels of conditionality so that you can do + * just what you need to do, and no more. If neither of these defines + * are used, the bits won't be there, and VALIDATE_DRAWABLE_AND_GC will + * be unchanged. dpw + */ + +#if defined(NEED_DBE_BUF_BITS) +#define SET_DBE_DSTBUF(_pDraw, _drawID) \ + SET_DBE_BUF(_pDraw, _drawID, dstBuffer, TRUE) +#define SET_DBE_SRCBUF(_pDraw, _drawID) \ + SET_DBE_BUF(_pDraw, _drawID, srcBuffer, FALSE) +#if defined (NEED_DBE_BUF_VALIDATE) +#define SET_DBE_BUF(_pDraw, _drawID, _whichBuffer, _dstbuf) \ + if (_pDraw->type == DRAWABLE_WINDOW)\ + {\ + int thisbuf = (_pDraw->id == _drawID);\ + if (thisbuf != ((WindowPtr)_pDraw)->_whichBuffer)\ + {\ + ((WindowPtr)_pDraw)->_whichBuffer = thisbuf;\ + DbeValidateBuffer((WindowPtr)_pDraw, _drawID, _dstbuf);\ + }\ + } +#else /* want buffer bits, but don't need to call DbeValidateBuffer */ +#define SET_DBE_BUF(_pDraw, _drawID, _whichBuffer, _dstbuf) \ + if (_pDraw->type == DRAWABLE_WINDOW)\ + {\ + ((WindowPtr)_pDraw)->_whichBuffer = (_pDraw->id == _drawID);\ + } +#endif /* NEED_DBE_BUF_VALIDATE */ +#else /* don't want buffer bits in window */ +#define SET_DBE_DSTBUF(_pDraw, _drawID) /**/ +#define SET_DBE_SRCBUF(_pDraw, _drawID) /**/ +#endif /* NEED_DBE_BUF_BITS */ + +#define VALIDATE_DRAWABLE_AND_GC(drawID, pDraw, pGC, client)\ + if ((stuff->gc == INVALID) || (client->lastGCID != stuff->gc) ||\ + (client->lastDrawableID != drawID))\ + {\ + SECURITY_VERIFY_GEOMETRABLE(pDraw, drawID, client, SecurityWriteAccess);\ + SECURITY_VERIFY_GC(pGC, stuff->gc, client, SecurityReadAccess);\ + if ((pGC->depth != pDraw->depth) ||\ + (pGC->pScreen != pDraw->pScreen))\ + return (BadMatch);\ + client->lastDrawable = pDraw;\ + client->lastDrawableID = drawID;\ + client->lastGC = pGC;\ + client->lastGCID = stuff->gc;\ + }\ + else\ + {\ + pGC = client->lastGC;\ + pDraw = client->lastDrawable;\ + }\ + SET_DBE_DSTBUF(pDraw, drawID);\ + if (pGC->serialNumber != pDraw->serialNumber)\ + ValidateGC(pDraw, pGC); + + +#define WriteReplyToClient(pClient, size, pReply) { \ + if ((pClient)->swapped) \ + (*ReplySwapVector[((xReq *)(pClient)->requestBuffer)->reqType]) \ + (pClient, (int)(size), pReply); \ + else (void) WriteToClient(pClient, (int)(size), (char *)(pReply)); } + +#define WriteSwappedDataToClient(pClient, size, pbuf) \ + if ((pClient)->swapped) \ + (*(pClient)->pSwapReplyFunc)(pClient, (int)(size), pbuf); \ + else (void) WriteToClient (pClient, (int)(size), (char *)(pbuf)); + +typedef struct _TimeStamp *TimeStampPtr; + +#ifndef _XTYPEDEF_CLIENTPTR +typedef struct _Client *ClientPtr; /* also in misc.h */ +#define _XTYPEDEF_CLIENTPTR +#endif + +typedef struct _WorkQueue *WorkQueuePtr; + +extern ClientPtr requestingClient; +extern ClientPtr clients[MAXCLIENTS]; +extern ClientPtr serverClient; +extern int currentMaxClients; +extern char dispatchExceptionAtReset; + +typedef int HWEventQueueType; +typedef HWEventQueueType* HWEventQueuePtr; + +extern HWEventQueuePtr checkForInput[2]; + +typedef struct _TimeStamp { + CARD32 months; /* really ~49.7 days */ + CARD32 milliseconds; +} TimeStamp; + +/* dispatch.c */ + +void SetInputCheck( + HWEventQueuePtr /*c0*/, + HWEventQueuePtr /*c1*/); + +void CloseDownClient( + ClientPtr /*client*/); + +void UpdateCurrentTime(void); + +void UpdateCurrentTimeIf(void); + +void InitSelections(void); + +void FlushClientCaches(XID /*id*/); + +int dixDestroyPixmap( + pointer /*value*/, + XID /*pid*/); + +void CloseDownRetainedResources(void); + +void InitClient( + ClientPtr /*client*/, + int /*i*/, + pointer /*ospriv*/); + +ClientPtr NextAvailableClient( + pointer /*ospriv*/); + +void SendErrorToClient( + ClientPtr /*client*/, + unsigned int /*majorCode*/, + unsigned int /*minorCode*/, + XID /*resId*/, + int /*errorCode*/); + +void DeleteWindowFromAnySelections( + WindowPtr /*pWin*/); + +void MarkClientException( + ClientPtr /*client*/); + +int GetGeometry( + ClientPtr /*client*/, + xGetGeometryReply* /* wa */); + +int SendConnSetup( + ClientPtr /*client*/, + const char* /*reason*/); + +int DoGetImage( + ClientPtr /*client*/, + int /*format*/, + Drawable /*drawable*/, + int /*x*/, + int /*y*/, + int /*width*/, + int /*height*/, + Mask /*planemask*/, + xGetImageReply ** /*im_return*/); + +/* dixutils.c */ + +int CompareISOLatin1Lowered( + unsigned char * /*a*/, + int alen, + unsigned char * /*b*/, + int blen); + + +WindowPtr LookupWindow( + XID /*rid*/, + ClientPtr /*client*/); + +pointer LookupDrawable( + XID /*rid*/, + ClientPtr /*client*/); + +#define SecurityLookupWindow(rid, client, access_mode) \ + LookupWindow(rid, client) + +#define SecurityLookupDrawable(rid, client, access_mode) \ + LookupDrawable(rid, client) + + +ClientPtr LookupClient( + XID /*rid*/, + ClientPtr /*client*/); + +void NoopDDA(void); + +int AlterSaveSetForClient( + ClientPtr /*client*/, + WindowPtr /*pWin*/, + unsigned /*mode*/, + Bool /*toRoot*/, + Bool /*remap*/); + +void DeleteWindowFromAnySaveSet( + WindowPtr /*pWin*/); + +void BlockHandler( + pointer /*pTimeout*/, + pointer /*pReadmask*/); + +void WakeupHandler( + int /*result*/, + pointer /*pReadmask*/); + +typedef void (* WakeupHandlerProcPtr)( + pointer /* blockData */, + int /* result */, + pointer /* pReadmask */); + +Bool RegisterBlockAndWakeupHandlers( + BlockHandlerProcPtr /*blockHandler*/, + WakeupHandlerProcPtr /*wakeupHandler*/, + pointer /*blockData*/); + +void RemoveBlockAndWakeupHandlers( + BlockHandlerProcPtr /*blockHandler*/, + WakeupHandlerProcPtr /*wakeupHandler*/, + pointer /*blockData*/); + +void InitBlockAndWakeupHandlers(void); + +void ProcessWorkQueue(void); + +void ProcessWorkQueueZombies(void); + +Bool QueueWorkProc( + Bool (* /*function*/)( + ClientPtr /*clientUnused*/, + pointer /*closure*/), + ClientPtr /*client*/, + pointer /*closure*/ +); + +typedef Bool (* ClientSleepProcPtr)( + ClientPtr /*client*/, + pointer /*closure*/); + +Bool ClientSleep( + ClientPtr /*client*/, + ClientSleepProcPtr /* function */, + pointer /*closure*/); + +#ifndef ___CLIENTSIGNAL_DEFINED___ +#define ___CLIENTSIGNAL_DEFINED___ +Bool ClientSignal( + ClientPtr /*client*/); +#endif /* ___CLIENTSIGNAL_DEFINED___ */ + +void ClientWakeup( + ClientPtr /*client*/); + +Bool ClientIsAsleep( + ClientPtr /*client*/); + +/* atom.c */ + +Atom MakeAtom( + char * /*string*/, + unsigned /*len*/, + Bool /*makeit*/); + +Bool ValidAtom( + Atom /*atom*/); + +char *NameForAtom( + Atom /*atom*/); + +void AtomError(void); + +void FreeAllAtoms(void); + +void InitAtoms(void); + +/* events.c */ + +void SetMaskForEvent( + Mask /* mask */, + int /* event */); + + +Bool IsParent( + WindowPtr /* maybeparent */, + WindowPtr /* child */); + +WindowPtr GetCurrentRootWindow(void); + +WindowPtr GetSpriteWindow(void); + + +void NoticeEventTime(xEventPtr /* xE */); + +void EnqueueEvent( + xEventPtr /* xE */, + DeviceIntPtr /* device */, + int /* count */); + +void ComputeFreezes(void); + +void CheckGrabForSyncs( + DeviceIntPtr /* dev */, + Bool /* thisMode */, + Bool /* otherMode */); + +void ActivatePointerGrab( + DeviceIntPtr /* mouse */, + GrabPtr /* grab */, + TimeStamp /* time */, + Bool /* autoGrab */); + +void DeactivatePointerGrab( + DeviceIntPtr /* mouse */); + +void ActivateKeyboardGrab( + DeviceIntPtr /* keybd */, + GrabPtr /* grab */, + TimeStamp /* time */, + Bool /* passive */); + +void DeactivateKeyboardGrab( + DeviceIntPtr /* keybd */); + +void AllowSome( + ClientPtr /* client */, + TimeStamp /* time */, + DeviceIntPtr /* thisDev */, + int /* newState */); + +void ReleaseActiveGrabs( + ClientPtr client); + +int DeliverEventsToWindow( + WindowPtr /* pWin */, + xEventPtr /* pEvents */, + int /* count */, + Mask /* filter */, + GrabPtr /* grab */, + int /* mskidx */); + +int DeliverDeviceEvents( + WindowPtr /* pWin */, + xEventPtr /* xE */, + GrabPtr /* grab */, + WindowPtr /* stopAt */, + DeviceIntPtr /* dev */, + int /* count */); + +void DefineInitialRootWindow( + WindowPtr /* win */); + +void WindowHasNewCursor( + WindowPtr /* pWin */); + +Bool CheckDeviceGrabs( + DeviceIntPtr /* device */, + xEventPtr /* xE */, + int /* checkFirst */, + int /* count */); + +void DeliverFocusedEvent( + DeviceIntPtr /* keybd */, + xEventPtr /* xE */, + WindowPtr /* window */, + int /* count */); + +void DeliverGrabbedEvent( + xEventPtr /* xE */, + DeviceIntPtr /* thisDev */, + Bool /* deactivateGrab */, + int /* count */); + + +void RecalculateDeliverableEvents( + WindowPtr /* pWin */); + +int OtherClientGone( + pointer /* value */, + XID /* id */); + +void DoFocusEvents( + DeviceIntPtr /* dev */, + WindowPtr /* fromWin */, + WindowPtr /* toWin */, + int /* mode */); + +int SetInputFocus( + ClientPtr /* client */, + DeviceIntPtr /* dev */, + Window /* focusID */, + CARD8 /* revertTo */, + Time /* ctime */, + Bool /* followOK */); + +int GrabDevice( + ClientPtr /* client */, + DeviceIntPtr /* dev */, + unsigned /* this_mode */, + unsigned /* other_mode */, + Window /* grabWindow */, + unsigned /* ownerEvents */, + Time /* ctime */, + Mask /* mask */, + CARD8 * /* status */); + +void InitEvents(void); + +void CloseDownEvents(void); + +void DeleteWindowFromAnyEvents( + WindowPtr /* pWin */, + Bool /* freeResources */); + + +Mask EventMaskForClient( + WindowPtr /* pWin */, + ClientPtr /* client */); + + + +int DeliverEvents( + WindowPtr /*pWin*/, + xEventPtr /*xE*/, + int /*count*/, + WindowPtr /*otherParent*/); + + +void WriteEventsToClient( + ClientPtr /*pClient*/, + int /*count*/, + xEventPtr /*events*/); + +int TryClientEvents( + ClientPtr /*client*/, + xEventPtr /*pEvents*/, + int /*count*/, + Mask /*mask*/, + Mask /*filter*/, + GrabPtr /*grab*/); + +void WindowsRestructured(void); + + +void +ScreenRestructured (ScreenPtr pScreen); + +void ResetClientPrivates(void); + +int AllocateClientPrivateIndex(void); + +Bool AllocateClientPrivate( + int /*index*/, + unsigned /*amount*/); + +/* + * callback manager stuff + */ + +#ifndef _XTYPEDEF_CALLBACKLISTPTR +typedef struct _CallbackList *CallbackListPtr; /* also in misc.h */ +#define _XTYPEDEF_CALLBACKLISTPTR +#endif + +typedef void (*CallbackProcPtr) ( + CallbackListPtr *, pointer, pointer); + +typedef Bool (*AddCallbackProcPtr) ( + CallbackListPtr *, CallbackProcPtr, pointer); + +typedef Bool (*DeleteCallbackProcPtr) ( + CallbackListPtr *, CallbackProcPtr, pointer); + +typedef void (*CallCallbacksProcPtr) ( + CallbackListPtr *, pointer); + +typedef void (*DeleteCallbackListProcPtr) ( + CallbackListPtr *); + +typedef struct _CallbackProcs { + AddCallbackProcPtr AddCallback; + DeleteCallbackProcPtr DeleteCallback; + CallCallbacksProcPtr CallCallbacks; + DeleteCallbackListProcPtr DeleteCallbackList; +} CallbackFuncsRec, *CallbackFuncsPtr; + +Bool CreateCallbackList( + CallbackListPtr * /*pcbl*/, + CallbackFuncsPtr /*cbfuncs*/); + +Bool AddCallback( + CallbackListPtr * /*pcbl*/, + CallbackProcPtr /*callback*/, + pointer /*data*/); + +Bool DeleteCallback( + CallbackListPtr * /*pcbl*/, + CallbackProcPtr /*callback*/, + pointer /*data*/); + +void CallCallbacks( + CallbackListPtr * /*pcbl*/, + pointer /*call_data*/); + +void DeleteCallbackList( + CallbackListPtr * /*pcbl*/); + +void InitCallbackManager(void); + +/* + * ServerGrabCallback stuff + */ + +extern CallbackListPtr ServerGrabCallback; + +typedef enum {SERVER_GRABBED, SERVER_UNGRABBED, + CLIENT_PERVIOUS, CLIENT_IMPERVIOUS } ServerGrabState; + +typedef struct { + ClientPtr client; + ServerGrabState grabstate; +} ServerGrabInfoRec; + +/* + * EventCallback stuff + */ + +extern CallbackListPtr EventCallback; + +typedef struct { + ClientPtr client; + xEventPtr events; + int count; +} EventInfoRec; + +/* + * DeviceEventCallback stuff + */ + +extern CallbackListPtr DeviceEventCallback; + +typedef struct { + xEventPtr events; + int count; +} DeviceEventInfoRec; + +/* + * SelectionCallback stuff + */ + +extern CallbackListPtr SelectionCallback; + +typedef enum { + SelectionSetOwner, + SelectionWindowDestroy, + SelectionClientClose +} SelectionCallbackKind; + +typedef struct { + struct _Selection *selection; + SelectionCallbackKind kind; +} SelectionInfoRec; + +/* strcasecmp.c */ +#if NEED_STRCASECMP +#define strcasecmp xstrcasecmp +int xstrcasecmp(char *s1, char *s2); +#endif + +/* ffs.c */ +int ffs(int i); + +#endif /* DIX_H */ diff --git a/include/dixevents.h b/include/dixevents.h new file mode 100644 index 0000000..940afe7 --- /dev/null +++ b/include/dixevents.h @@ -0,0 +1,97 @@ +/************************************************************ + +Copyright 1996 by Thomas E. Dickey + + 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. + +********************************************************/ + +#ifndef DIXEVENTS_H +#define DIXEVENTS_H + +void SetCriticalEvent(int /* event */); + +CursorPtr GetSpriteCursor(void); + +int ProcAllowEvents(ClientPtr /* client */); + +int MaybeDeliverEventsToClient( + WindowPtr /* pWin */, + xEvent * /* pEvents */, + int /* count */, + Mask /* filter */, + ClientPtr /* dontClient */); + +int ProcWarpPointer(ClientPtr /* client */); + +#if 0 +extern void +ProcessKeyboardEvent ( + xEvent * /* xE */, + DeviceIntPtr /* keybd */, + int /* count */); + +extern void +ProcessPointerEvent ( + xEvent * /* xE */, + DeviceIntPtr /* mouse */, + int /* count */); +#endif + +int EventSelectForWindow( + WindowPtr /* pWin */, + ClientPtr /* client */, + Mask /* mask */); + +int EventSuppressForWindow( + WindowPtr /* pWin */, + ClientPtr /* client */, + Mask /* mask */, + Bool * /* checkOptional */); + +int ProcSetInputFocus(ClientPtr /* client */); + +int ProcGetInputFocus(ClientPtr /* client */); + +int ProcGrabPointer(ClientPtr /* client */); + +int ProcChangeActivePointerGrab(ClientPtr /* client */); + +int ProcUngrabPointer(ClientPtr /* client */); + +int ProcGrabKeyboard(ClientPtr /* client */); + +int ProcUngrabKeyboard(ClientPtr /* client */); + +int ProcQueryPointer(ClientPtr /* client */); + +int ProcSendEvent(ClientPtr /* client */); + +int ProcUngrabKey(ClientPtr /* client */); + +int ProcGrabKey(ClientPtr /* client */); + +int ProcGrabButton(ClientPtr /* client */); + +int ProcUngrabButton(ClientPtr /* client */); + +int ProcRecolorCursor(ClientPtr /* client */); + +#endif /* DIXEVENTS_H */ diff --git a/include/dixfont.h b/include/dixfont.h new file mode 100644 index 0000000..4b5694e --- /dev/null +++ b/include/dixfont.h @@ -0,0 +1,150 @@ +/*********************************************************** +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. + +******************************************************************/ + +#ifndef DIXFONT_H +#define DIXFONT_H 1 + +#include "dix.h" +#include +#include "closure.h" +#include + +#define NullDIXFontProp ((DIXFontPropPtr)0) + +typedef struct _DIXFontProp *DIXFontPropPtr; + +extern FPEFunctions *fpe_functions; + +int FontToXError(int /*err*/); + +Bool SetDefaultFont(char * /*defaultfontname*/); + +void QueueFontWakeup(FontPathElementPtr /*fpe*/); + +void RemoveFontWakeup(FontPathElementPtr /*fpe*/); + +void FontWakeup(pointer /*data*/, + int /*count*/, + pointer /*LastSelectMask*/); + +int OpenFont(ClientPtr /*client*/, + XID /*fid*/, + Mask /*flags*/, + unsigned /*lenfname*/, + char * /*pfontname*/); + +int CloseFont(pointer /*pfont*/, + XID /*fid*/); + +typedef struct _xQueryFontReply *xQueryFontReplyPtr; + +void QueryFont(FontPtr /*pFont*/, + xQueryFontReplyPtr /*pReply*/, + int /*nProtoCCIStructs*/); + +int ListFonts(ClientPtr /*client*/, + unsigned char * /*pattern*/, + unsigned int /*length*/, + unsigned int /*max_names*/); + +int +doListFontsWithInfo(ClientPtr /*client*/, + LFWIclosurePtr /*c*/); + +int doPolyText(ClientPtr /*client*/, + PTclosurePtr /*c*/ +); + +int PolyText(ClientPtr /*client*/, + DrawablePtr /*pDraw*/, + GCPtr /*pGC*/, + unsigned char * /*pElt*/, + unsigned char * /*endReq*/, + int /*xorg*/, + int /*yorg*/, + int /*reqType*/, + XID /*did*/); + +int doImageText(ClientPtr /*client*/, + ITclosurePtr /*c*/); + +int ImageText(ClientPtr /*client*/, + DrawablePtr /*pDraw*/, + GCPtr /*pGC*/, + int /*nChars*/, + unsigned char * /*data*/, + int /*xorg*/, + int /*yorg*/, + int /*reqType*/, + XID /*did*/); + +int SetFontPath(ClientPtr /*client*/, + int /*npaths*/, + unsigned char * /*paths*/, + int * /*error*/); + +int SetDefaultFontPath(char * /*path*/); + +unsigned char *GetFontPath(int * /*count*/, + int * /*length*/); + +int LoadGlyphs(ClientPtr /*client*/, + FontPtr /*pfont*/, + unsigned /*nchars*/, + int /*item_size*/, + unsigned char * /*data*/); + +void DeleteClientFontStuff(ClientPtr /*client*/); + +/* Quartz support on Mac OS X pulls in the QuickDraw + framework whose InitFonts function conflicts here. */ +void InitFonts(void); + +void FreeFonts(void); + +FontPtr find_old_font(XID /*id*/); + +void GetGlyphs(FontPtr /*font*/, + unsigned long /*count*/, + unsigned char * /*chars*/, + FontEncoding /*fontEncoding*/, + unsigned long * /*glyphcount*/, + CharInfoPtr * /*glyphs*/); + +void QueryGlyphExtents(FontPtr /*pFont*/, + CharInfoPtr * /*charinfo*/, + unsigned long /*count*/, + ExtentInfoPtr /*info*/); + +Bool QueryTextExtents(FontPtr /*pFont*/, + unsigned long /*count*/, + unsigned char * /*chars*/, + ExtentInfoPtr /*info*/); + +Bool ParseGlyphCachingMode(char * /*str*/); + +void InitGlyphCaching(void); + +void SetGlyphCachingMode(int /*newmode*/); + +#endif /* DIXFONT_H */ diff --git a/include/dixfontstr.h b/include/dixfontstr.h new file mode 100644 index 0000000..c559e86 --- /dev/null +++ b/include/dixfontstr.h @@ -0,0 +1,93 @@ +/*********************************************************** +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. + +******************************************************************/ + +#ifndef DIXFONTSTRUCT_H +#define DIXFONTSTRUCT_H + +#include "servermd.h" +#include "dixfont.h" +#include +#include "closure.h" +#include /* for xQueryFontReply */ + +#define FONTCHARSET(font) (font) +#define FONTMAXBOUNDS(font,field) (font)->info.maxbounds.field +#define FONTMINBOUNDS(font,field) (font)->info.minbounds.field +#define TERMINALFONT(font) (font)->info.terminalFont +#define FONTASCENT(font) (font)->info.fontAscent +#define FONTDESCENT(font) (font)->info.fontDescent +#define FONTGLYPHS(font) 0 +#define FONTCONSTMETRICS(font) (font)->info.constantMetrics +#define FONTCONSTWIDTH(font) (font)->info.constantWidth +#define FONTALLEXIST(font) (font)->info.allExist +#define FONTFIRSTCOL(font) (font)->info.firstCol +#define FONTLASTCOL(font) (font)->info.lastCol +#define FONTFIRSTROW(font) (font)->info.firstRow +#define FONTLASTROW(font) (font)->info.lastRow +#define FONTDEFAULTCH(font) (font)->info.defaultCh +#define FONTINKMIN(font) (&((font)->info.ink_minbounds)) +#define FONTINKMAX(font) (&((font)->info.ink_maxbounds)) +#define FONTPROPS(font) (font)->info.props +#define FONTGLYPHBITS(base,pci) ((unsigned char *) (pci)->bits) +#define FONTINFONPROPS(font) (font)->info.nprops + +/* some things haven't changed names, but we'll be careful anyway */ + +#define FONTREFCNT(font) (font)->refcnt + +/* + * for linear char sets + */ +#define N1dChars(pfont) (FONTLASTCOL(pfont) - FONTFIRSTCOL(pfont) + 1) + +/* + * for 2D char sets + */ +#define N2dChars(pfont) (N1dChars(pfont) * \ + (FONTLASTROW(pfont) - FONTFIRSTROW(pfont) + 1)) + +#ifndef GLYPHPADBYTES +#define GLYPHPADBYTES -1 +#endif + +#if GLYPHPADBYTES == 0 || GLYPHPADBYTES == 1 +#define GLYPHWIDTHBYTESPADDED(pci) (GLYPHWIDTHBYTES(pci)) +#define PADGLYPHWIDTHBYTES(w) (((w)+7)>>3) +#endif + +#if GLYPHPADBYTES == 2 +#define GLYPHWIDTHBYTESPADDED(pci) ((GLYPHWIDTHBYTES(pci)+1) & ~0x1) +#define PADGLYPHWIDTHBYTES(w) (((((w)+7)>>3)+1) & ~0x1) +#endif + +#if GLYPHPADBYTES == 4 +#define GLYPHWIDTHBYTESPADDED(pci) ((GLYPHWIDTHBYTES(pci)+3) & ~0x3) +#define PADGLYPHWIDTHBYTES(w) (((((w)+7)>>3)+3) & ~0x3) +#endif + +#if GLYPHPADBYTES == 8 /* for a cray? */ +#define GLYPHWIDTHBYTESPADDED(pci) ((GLYPHWIDTHBYTES(pci)+7) & ~0x7) +#define PADGLYPHWIDTHBYTES(w) (((((w)+7)>>3)+7) & ~0x7) +#endif + +#endif /* DIXFONTSTRUCT_H */ diff --git a/include/dixgrabs.h b/include/dixgrabs.h new file mode 100644 index 0000000..0009c1d --- /dev/null +++ b/include/dixgrabs.h @@ -0,0 +1,58 @@ +/************************************************************ + +Copyright 1996 by Thomas E. Dickey + + 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. + +********************************************************/ + +#ifndef DIXGRABS_H +#define DIXGRABS_H 1 + +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 */, + WindowPtr /* confineTo */, + CursorPtr /* cursor */); + +int DeletePassiveGrab( + pointer /* value */, + XID /* id */); + +Bool GrabMatchesSecond( + GrabPtr /* pFirstGrab */, + GrabPtr /* pSecondGrab */); + +int AddPassiveGrabToList( + GrabPtr /* pGrab */); + +Bool DeletePassiveGrabFromList( + GrabPtr /* pMinuendGrab */); + +#endif /* DIXGRABS_H */ diff --git a/include/dixstruct.h b/include/dixstruct.h new file mode 100644 index 0000000..6734695 --- /dev/null +++ b/include/dixstruct.h @@ -0,0 +1,195 @@ +/*********************************************************** +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. + +******************************************************************/ + +#ifndef DIXSTRUCT_H +#define DIXSTRUCT_H + +#include "dix.h" +#include "resource.h" +#include "cursor.h" +#include "gc.h" +#include "pixmap.h" +#include + +/* + * direct-mapped hash table, used by resource manager to store + * translation from client ids to server addresses. + */ + +#ifdef DEBUG +#define MAX_REQUEST_LOG 100 +#endif + +extern CallbackListPtr ClientStateCallback; + +typedef struct { + ClientPtr client; + xConnSetupPrefix *prefix; + xConnSetup *setup; +} NewClientInfoRec; + +typedef void (*ReplySwapPtr) ( + ClientPtr /* pClient */, + int /* size */, + void * /* pbuf */); + +void ReplyNotSwappd ( + ClientPtr /* pClient */, + int /* size */, + void * /* pbuf */); + +typedef enum {ClientStateInitial, + ClientStateAuthenticating, + ClientStateRunning, + ClientStateRetained, + ClientStateGone, + ClientStateCheckingSecurity, + ClientStateCheckedSecurity} ClientState; + +typedef struct _saveSet { + struct _Window *windowPtr; + Bool toRoot; + Bool remap; +} SaveSetElt; +#define SaveSetWindow(ss) ((ss).windowPtr) +#define SaveSetToRoot(ss) ((ss).toRoot) +#define SaveSetRemap(ss) ((ss).remap) +#define SaveSetAssignWindow(ss,w) ((ss).windowPtr = (w)) +#define SaveSetAssignToRoot(ss,tr) ((ss).toRoot = (tr)) +#define SaveSetAssignRemap(ss,rm) ((ss).remap = (rm)) + +typedef struct _Client { + int index; + Mask clientAsMask; + pointer requestBuffer; + pointer osPrivate; /* for OS layer, including scheduler */ + Bool swapped; + ReplySwapPtr pSwapReplyFunc; + XID errorValue; + int sequence; + int closeDownMode; + int clientGone; + int noClientException; /* this client died or needs to be + * killed */ + DrawablePtr lastDrawable; + Drawable lastDrawableID; + GCPtr lastGC; + GContext lastGCID; + SaveSetElt *saveSet; + int numSaved; + pointer screenPrivate[MAXSCREENS]; + int (**requestVector) ( + ClientPtr /* pClient */); + CARD32 req_len; /* length of current request */ + Bool big_requests; /* supports large requests */ + int priority; + ClientState clientState; + DevUnion *devPrivates; + +#ifdef DEBUG + unsigned char requestLog[MAX_REQUEST_LOG]; + int requestLogIndex; +#endif + unsigned long replyBytesRemaining; + struct _FontResolution * (*fontResFunc) ( /* no need for font.h */ + ClientPtr /* pClient */, + int * /* num */); +#ifdef SMART_SCHEDULE + int smart_priority; + long smart_start_tick; + long smart_stop_tick; + long smart_check_tick; +#endif +} ClientRec; + +#ifdef SMART_SCHEDULE +/* + * Scheduling interface + */ +extern long SmartScheduleTime; +extern long SmartScheduleInterval; +extern long SmartScheduleSlice; +extern long SmartScheduleMaxSlice; +extern unsigned long SmartScheduleIdleCount; +extern Bool SmartScheduleDisable; +extern Bool SmartScheduleIdle; +extern Bool SmartScheduleTimerStopped; +Bool SmartScheduleStartTimer(void); +#define SMART_MAX_PRIORITY (20) +#define SMART_MIN_PRIORITY (-20) + +Bool SmartScheduleInit(void); + +#endif + +/* This prototype is used pervasively in Xext, dix */ +#define DISPATCH_PROC(func) int func(ClientPtr /* client */) + +typedef struct _WorkQueue { + struct _WorkQueue *next; + Bool (*function) ( + ClientPtr /* pClient */, + pointer /* closure */ +); + ClientPtr client; + pointer closure; +} WorkQueueRec; + +extern TimeStamp currentTime; +extern TimeStamp lastDeviceEventTime; + +int CompareTimeStamps( + TimeStamp /*a*/, + TimeStamp /*b*/); + +TimeStamp ClientTimeToServerTime(CARD32 /*c*/); + +typedef struct _CallbackRec { + CallbackProcPtr proc; + pointer data; + Bool deleted; + struct _CallbackRec *next; +} CallbackRec, *CallbackPtr; + +typedef struct _CallbackList { + CallbackFuncsRec funcs; + int inCallback; + Bool deleted; + int numDeleted; + CallbackPtr list; +} CallbackListRec; + +/* proc vectors */ + +int (* InitialVector[3]) (ClientPtr /*client*/); + +int (* ProcVector[256]) (ClientPtr /*client*/); + +int (* SwappedProcVector[256]) (ClientPtr /*client*/); + + +extern ReplySwapPtr ReplySwapVector[256]; + +int ProcBadRequest(ClientPtr /*client*/); + +#endif /* DIXSTRUCT_H */ diff --git a/include/exevents.h b/include/exevents.h new file mode 100644 index 0000000..d6224a6 --- /dev/null +++ b/include/exevents.h @@ -0,0 +1,182 @@ +/************************************************************ + +Copyright 1996 by Thomas E. Dickey + + 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. + +********************************************************/ + +/******************************************************************** + * Interface of 'exevents.c' + */ + +#ifndef EXEVENTS_H +#define EXEVENTS_H + +void RegisterOtherDevice ( + DeviceIntPtr /* device */); + +void ProcessOtherEvent ( + xEventPtr /* FIXME deviceKeyButtonPointer * xE */, + DeviceIntPtr /* other */, + int /* count */); + +int InitProximityClassDeviceStruct( + DeviceIntPtr /* dev */); + +void InitValuatorAxisStruct( + DeviceIntPtr /* dev */, + int /* axnum */, + int /* minval */, + int /* maxval */, + int /* resolution */, + int /* min_res */, + int /* max_res */); + +void DeviceFocusEvent( + DeviceIntPtr /* dev */, + int /* type */, + int /* mode */, + int /* detail */, + WindowPtr /* pWin */); + +int GrabButton( + ClientPtr /* client */, + DeviceIntPtr /* dev */, + BYTE /* this_device_mode */, + BYTE /* other_devices_mode */, + CARD16 /* modifiers */, + DeviceIntPtr /* modifier_device */, + CARD8 /* button */, + Window /* grabWindow */, + BOOL /* ownerEvents */, + Cursor /* rcursor */, + Window /* rconfineTo */, + Mask /* eventMask */); + +int GrabKey( + ClientPtr /* client */, + DeviceIntPtr /* dev */, + BYTE /* this_device_mode */, + BYTE /* other_devices_mode */, + CARD16 /* modifiers */, + DeviceIntPtr /* modifier_device */, + CARD8 /* key */, + Window /* grabWindow */, + BOOL /* ownerEvents */, + Mask /* mask */); + +int SelectForWindow( + DeviceIntPtr /* dev */, + WindowPtr /* pWin */, + ClientPtr /* client */, + Mask /* mask */, + Mask /* exclusivemasks */, + Mask /* validmasks */); + +int AddExtensionClient ( + WindowPtr /* pWin */, + ClientPtr /* client */, + Mask /* mask */, + int /* mskidx */); + +void RecalculateDeviceDeliverableEvents( + WindowPtr /* pWin */); + +int InputClientGone( + WindowPtr /* pWin */, + XID /* id */); + +int SendEvent ( + ClientPtr /* client */, + DeviceIntPtr /* d */, + Window /* dest */, + Bool /* propagate */, + xEvent * /* ev */, + Mask /* mask */, + int /* count */); + +int SetButtonMapping ( + ClientPtr /* client */, + DeviceIntPtr /* dev */, + int /* nElts */, + BYTE * /* map */); + +int SetModifierMapping( + ClientPtr /* client */, + DeviceIntPtr /* dev */, + int /* len */, + int /* rlen */, + int /* numKeyPerModifier */, + KeyCode * /* inputMap */, + KeyClassPtr * /* k */); + +void SendDeviceMappingNotify( + CARD8 /* request, */, + KeyCode /* firstKeyCode */, + CARD8 /* count */, + DeviceIntPtr /* dev */); + +int ChangeKeyMapping( + ClientPtr /* client */, + DeviceIntPtr /* dev */, + unsigned /* len */, + int /* type */, + KeyCode /* firstKeyCode */, + CARD8 /* keyCodes */, + CARD8 /* keySymsPerKeyCode */, + KeySym * /* map */); + +void DeleteWindowFromAnyExtEvents( + WindowPtr /* pWin */, + Bool /* freeResources */); + +void DeleteDeviceFromAnyExtEvents( + WindowPtr /* pWin */, + DeviceIntPtr /* dev */); + +int MaybeSendDeviceMotionNotifyHint ( + deviceKeyButtonPointer * /* pEvents */, + Mask /* mask */); + +void CheckDeviceGrabAndHintWindow ( + WindowPtr /* pWin */, + int /* type */, + deviceKeyButtonPointer * /* xE */, + GrabPtr /* grab */, + ClientPtr /* client */, + Mask /* deliveryMask */); + +Mask DeviceEventMaskForClient( + DeviceIntPtr /* dev */, + WindowPtr /* pWin */, + ClientPtr /* client */); + +void MaybeStopDeviceHint( + DeviceIntPtr /* dev */, + ClientPtr /* client */); + +int DeviceEventSuppressForWindow( + WindowPtr /* pWin */, + ClientPtr /* client */, + Mask /* mask */, + int /* maskndx */); + +#endif /* EXEVENTS_H */ diff --git a/include/extension.h b/include/extension.h new file mode 100644 index 0000000..f370841 --- /dev/null +++ b/include/extension.h @@ -0,0 +1,71 @@ +/*********************************************************** + +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. + +******************************************************************/ + +#ifndef EXTENSION_H +#define EXTENSION_H + +_XFUNCPROTOBEGIN + +unsigned short StandardMinorOpcode(ClientPtr /*client*/); + +unsigned short MinorOpcodeOfRequest(ClientPtr /*client*/); + +Bool EnableDisableExtension(char *name, Bool enable); + +void EnableDisableExtensionError(char *name, Bool enable); + +void ResetExtensionPrivates(void); + +void InitExtensions(int argc, char **argv); + +void InitVisualWrap(void); + +void CloseDownExtensions(void); + +_XFUNCPROTOEND + +#endif /* EXTENSION_H */ diff --git a/include/extinit.h b/include/extinit.h new file mode 100644 index 0000000..f7b0d87 --- /dev/null +++ b/include/extinit.h @@ -0,0 +1,166 @@ +/************************************************************ + +Copyright 1996 by Thomas E. Dickey + + 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. + +********************************************************/ + +/******************************************************************** + * Interface of extinit.c + */ + +#ifndef EXTINIT_H +#define EXTINIT_H + +#include "extnsionst.h" +#include + +void +XInputExtensionInit( + void + ); + + +int +ProcIDispatch ( + ClientPtr /* client */ + ); + +int +SProcIDispatch( + ClientPtr /* client */ + ); + +void +SReplyIDispatch ( + ClientPtr /* client */, + int /* len */, + xGrabDeviceReply * /* rep */ + ); + +void +SEventIDispatch ( + xEvent * /* from */, + xEvent * /* to */ + ); + +void +SEventDeviceValuator ( + deviceValuator * /* from */, + deviceValuator * /* to */ + ); + +void +SEventFocus ( + deviceFocus * /* from */, + deviceFocus * /* to */ + ); + +void +SDeviceStateNotifyEvent ( + deviceStateNotify * /* from */, + deviceStateNotify * /* to */ + ); + +void +SDeviceKeyStateNotifyEvent ( + deviceKeyStateNotify * /* from */, + deviceKeyStateNotify * /* to */ + ); + +void +SDeviceButtonStateNotifyEvent ( + deviceButtonStateNotify * /* from */, + deviceButtonStateNotify * /* to */ + ); + +void +SChangeDeviceNotifyEvent ( + changeDeviceNotify * /* from */, + changeDeviceNotify * /* to */ + ); + +void +SDeviceMappingNotifyEvent ( + deviceMappingNotify * /* from */, + deviceMappingNotify * /* to */ + ); + +void +FixExtensionEvents ( + ExtensionEntry * /* extEntry */ + ); + +void +RestoreExtensionEvents ( + void + ); + +void +IResetProc( + ExtensionEntry * /* unused */ + ); + +void +AssignTypeAndName ( + DeviceIntPtr /* dev */, + Atom /* type */, + char * /* name */ + ); + +void +MakeDeviceTypeAtoms ( + void +); + +DeviceIntPtr +LookupDeviceIntRec ( + CARD8 /* id */ + ); + +void +SetExclusiveAccess ( + Mask /* mask */ + ); + +void +AllowPropagateSuppress ( + Mask /* mask */ + ); + +Mask +GetNextExtEventMask ( + void +); + +void +SetMaskForExtEvent( + Mask /* mask */, + int /* event */ + ); + +void +SetEventInfo( + Mask /* mask */, + int /* constant */ + ); + +#endif /* EXTINIT_H */ diff --git a/include/extnsionst.h b/include/extnsionst.h new file mode 100644 index 0000000..12b88a9 --- /dev/null +++ b/include/extnsionst.h @@ -0,0 +1,143 @@ +/*********************************************************** + +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. + +******************************************************************/ + +#ifndef EXTENSIONSTRUCT_H +#define EXTENSIONSTRUCT_H + +#include "dix.h" +#include "misc.h" +#include "screenint.h" +#include "extension.h" +#include "gc.h" + +typedef struct _ExtensionEntry { + int index; + void (* CloseDown)( /* called at server shutdown */ + struct _ExtensionEntry * /* extension */); + char *name; /* extension name */ + int base; /* base request number */ + int eventBase; + int eventLast; + int errorBase; + int errorLast; + int num_aliases; + char **aliases; + pointer extPrivate; + unsigned short (* MinorOpcode)( /* called for errors */ + ClientPtr /* client */); + DevUnion *devPrivates; +} ExtensionEntry; + +/* + * The arguments may be different for extension event swapping functions. + * Deal with this by casting when initializing the event's EventSwapVector[] + * entries. + */ +typedef void (*EventSwapPtr) (xEvent *, xEvent *); + +extern EventSwapPtr EventSwapVector[128]; + +void NotImplemented ( /* FIXME: this may move to another file... */ + xEvent *, + xEvent *); + +typedef void (* ExtensionLookupProc)( +#ifdef EXTENSION_PROC_ARGS + EXTENSION_PROC_ARGS +#else + /* args no longer indeterminate */ + char *name, + GCPtr pGC +#endif +); + +typedef struct _ProcEntry { + char *name; + ExtensionLookupProc proc; +} ProcEntryRec, *ProcEntryPtr; + +typedef struct _ScreenProcEntry { + int num; + ProcEntryPtr procList; +} ScreenProcEntry; + +#define SetGCVector(pGC, VectorElement, NewRoutineAddress, Atom) \ + pGC->VectorElement = NewRoutineAddress; + +#define GetGCValue(pGC, GCElement) (pGC->GCElement) + + +ExtensionEntry *AddExtension( + char* /*name*/, + int /*NumEvents*/, + int /*NumErrors*/, + int (* /*MainProc*/)(ClientPtr /*client*/), + int (* /*SwappedMainProc*/)(ClientPtr /*client*/), + void (* /*CloseDownProc*/)(ExtensionEntry * /*extension*/), + unsigned short (* /*MinorOpcodeProc*/)(ClientPtr /*client*/) +); + +ExtensionLookupProc LookupProc( + char* /*name*/, + GCPtr /*pGC*/); + +Bool RegisterProc( + char* /*name*/, + GCPtr /*pGC*/, + ExtensionLookupProc /*proc*/); + +Bool RegisterScreenProc( + char* /*name*/, + ScreenPtr /*pScreen*/, + ExtensionLookupProc /*proc*/); + +void DeclareExtensionSecurity( + char * /*extname*/, + Bool /*secure*/); + +#endif /* EXTENSIONSTRUCT_H */ + diff --git a/include/gc.h b/include/gc.h new file mode 100644 index 0000000..0c33683 --- /dev/null +++ b/include/gc.h @@ -0,0 +1,176 @@ +/*********************************************************** + +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. + +******************************************************************/ + +#ifndef GC_H +#define GC_H + +#include /* for GContext, Mask */ +#include /* for Bool */ +#include +#include "screenint.h" /* for ScreenPtr */ +#include "pixmap.h" /* for DrawablePtr */ + +/* clientClipType field in GC */ +#define CT_NONE 0 +#define CT_PIXMAP 1 +#define CT_REGION 2 +#define CT_UNSORTED 6 +#define CT_YSORTED 10 +#define CT_YXSORTED 14 +#define CT_YXBANDED 18 + +#define GCQREASON_VALIDATE 1 +#define GCQREASON_CHANGE 2 +#define GCQREASON_COPY_SRC 3 +#define GCQREASON_COPY_DST 4 +#define GCQREASON_DESTROY 5 + +#define GC_CHANGE_SERIAL_BIT (((unsigned long)1)<<31) +#define GC_CALL_VALIDATE_BIT (1L<<30) +#define GCExtensionInterest (1L<<29) + +#define DRAWABLE_SERIAL_BITS (~(GC_CHANGE_SERIAL_BIT)) + +#define MAX_SERIAL_NUM (1L<<28) + +#define NEXT_SERIAL_NUMBER ((++globalSerialNumber) > MAX_SERIAL_NUM ? \ + (globalSerialNumber = 1): globalSerialNumber) + +typedef struct _GCInterest *GCInterestPtr; +typedef struct _GC *GCPtr; +typedef struct _GCOps *GCOpsPtr; + +void ValidateGC( + DrawablePtr /*pDraw*/, + GCPtr /*pGC*/); + +int ChangeGC( + GCPtr/*pGC*/, + BITS32 /*mask*/, + XID* /*pval*/); + +int DoChangeGC( + GCPtr/*pGC*/, + BITS32 /*mask*/, + XID* /*pval*/, + int /*fPointer*/); + +typedef union { + CARD32 val; + pointer ptr; +} ChangeGCVal, *ChangeGCValPtr; + +int dixChangeGC( + ClientPtr /*client*/, + GCPtr /*pGC*/, + BITS32 /*mask*/, + CARD32 * /*pval*/, + ChangeGCValPtr /*pCGCV*/); + +GCPtr CreateGC( + DrawablePtr /*pDrawable*/, + BITS32 /*mask*/, + XID* /*pval*/, + int* /*pStatus*/); + +int CopyGC( + GCPtr/*pgcSrc*/, + GCPtr/*pgcDst*/, + BITS32 /*mask*/); + +int FreeGC( + pointer /*pGC*/, + XID /*gid*/); + +void SetGCMask( + GCPtr /*pGC*/, + Mask /*selectMask*/, + Mask /*newDataMask*/); + +GCPtr CreateScratchGC( + ScreenPtr /*pScreen*/, + unsigned /*depth*/); + +void FreeGCperDepth( + int /*screenNum*/); + +Bool CreateGCperDepth( + int /*screenNum*/); + +Bool CreateDefaultStipple( + int /*screenNum*/); + +void FreeDefaultStipple( + int /*screenNum*/); + +int SetDashes( + GCPtr /*pGC*/, + unsigned /*offset*/, + unsigned /*ndash*/, + unsigned char* /*pdash*/); + +int VerifyRectOrder( + int /*nrects*/, + xRectangle* /*prects*/, + int /*ordering*/); + +int SetClipRects( + GCPtr /*pGC*/, + int /*xOrigin*/, + int /*yOrigin*/, + int /*nrects*/, + xRectangle* /*prects*/, + int /*ordering*/); + +GCPtr GetScratchGC( + unsigned /*depth*/, + ScreenPtr /*pScreen*/); + +void FreeScratchGC( + GCPtr /*pGC*/); + +#endif /* GC_H */ diff --git a/include/gcstruct.h b/include/gcstruct.h new file mode 100644 index 0000000..481e50b --- /dev/null +++ b/include/gcstruct.h @@ -0,0 +1,322 @@ +/*********************************************************** + +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. + +******************************************************************/ + + + +#ifndef GCSTRUCT_H +#define GCSTRUCT_H + +#include "gc.h" + +#include "regionstr.h" +#include "region.h" +#include "pixmap.h" +#include "screenint.h" +#include + +/* + * functions which modify the state of the GC + */ + +typedef struct _GCFuncs { + void (* ValidateGC)( + GCPtr /*pGC*/, + unsigned long /*stateChanges*/, + DrawablePtr /*pDrawable*/); + + void (* ChangeGC)( + GCPtr /*pGC*/, + unsigned long /*mask*/); + + void (* CopyGC)( + GCPtr /*pGCSrc*/, + unsigned long /*mask*/, + GCPtr /*pGCDst*/); + + void (* DestroyGC)( + GCPtr /*pGC*/); + + void (* ChangeClip)( + GCPtr /*pGC*/, + int /*type*/, + pointer /*pvalue*/, + int /*nrects*/); + + void (* DestroyClip)( + GCPtr /*pGC*/); + + void (* CopyClip)( + GCPtr /*pgcDst*/, + GCPtr /*pgcSrc*/); + DevUnion devPrivate; +} GCFuncs; + +/* + * graphics operations invoked through a GC + */ + +typedef struct _GCOps { + void (* FillSpans)( + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*nInit*/, + DDXPointPtr /*pptInit*/, + int * /*pwidthInit*/, + int /*fSorted*/); + + void (* SetSpans)( + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + char * /*psrc*/, + DDXPointPtr /*ppt*/, + int * /*pwidth*/, + int /*nspans*/, + int /*fSorted*/); + + void (* PutImage)( + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*depth*/, + int /*x*/, + int /*y*/, + int /*w*/, + int /*h*/, + int /*leftPad*/, + int /*format*/, + char * /*pBits*/); + + RegionPtr (* CopyArea)( + DrawablePtr /*pSrc*/, + DrawablePtr /*pDst*/, + GCPtr /*pGC*/, + int /*srcx*/, + int /*srcy*/, + int /*w*/, + int /*h*/, + int /*dstx*/, + int /*dsty*/); + + RegionPtr (* CopyPlane)( + DrawablePtr /*pSrcDrawable*/, + DrawablePtr /*pDstDrawable*/, + GCPtr /*pGC*/, + int /*srcx*/, + int /*srcy*/, + int /*width*/, + int /*height*/, + int /*dstx*/, + int /*dsty*/, + unsigned long /*bitPlane*/); + void (* PolyPoint)( + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*mode*/, + int /*npt*/, + DDXPointPtr /*pptInit*/); + + void (* Polylines)( + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*mode*/, + int /*npt*/, + DDXPointPtr /*pptInit*/); + + void (* PolySegment)( + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*nseg*/, + xSegment * /*pSegs*/); + + void (* PolyRectangle)( + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*nrects*/, + xRectangle * /*pRects*/); + + void (* PolyArc)( + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*narcs*/, + xArc * /*parcs*/); + + void (* FillPolygon)( + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*shape*/, + int /*mode*/, + int /*count*/, + DDXPointPtr /*pPts*/); + + void (* PolyFillRect)( + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*nrectFill*/, + xRectangle * /*prectInit*/); + + void (* PolyFillArc)( + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*narcs*/, + xArc * /*parcs*/); + + int (* PolyText8)( + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*x*/, + int /*y*/, + int /*count*/, + char * /*chars*/); + + int (* PolyText16)( + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*x*/, + int /*y*/, + int /*count*/, + unsigned short * /*chars*/); + + void (* ImageText8)( + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*x*/, + int /*y*/, + int /*count*/, + char * /*chars*/); + + void (* ImageText16)( + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*x*/, + int /*y*/, + int /*count*/, + unsigned short * /*chars*/); + + void (* ImageGlyphBlt)( + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*x*/, + int /*y*/, + unsigned int /*nglyph*/, + CharInfoPtr * /*ppci*/, + pointer /*pglyphBase*/); + + void (* PolyGlyphBlt)( + DrawablePtr /*pDrawable*/, + GCPtr /*pGC*/, + int /*x*/, + int /*y*/, + unsigned int /*nglyph*/, + CharInfoPtr * /*ppci*/, + pointer /*pglyphBase*/); + + void (* PushPixels)( + GCPtr /*pGC*/, + PixmapPtr /*pBitMap*/, + DrawablePtr /*pDst*/, + int /*w*/, + int /*h*/, + int /*x*/, + int /*y*/); + + DevUnion devPrivate; +} GCOps; + +/* there is padding in the bit fields because the Sun compiler doesn't + * force alignment to 32-bit boundaries. losers. + */ +typedef struct _GC { + ScreenPtr pScreen; + unsigned char depth; + unsigned char alu; + unsigned short lineWidth; + unsigned short dashOffset; + unsigned short numInDashList; + unsigned char *dash; + unsigned int lineStyle : 2; + unsigned int capStyle : 2; + unsigned int joinStyle : 2; + unsigned int fillStyle : 2; + unsigned int fillRule : 1; + unsigned int arcMode : 1; + unsigned int subWindowMode : 1; + unsigned int graphicsExposures : 1; + unsigned int clientClipType : 2; /* CT_ */ + unsigned int miTranslate:1; /* should mi things translate? */ + unsigned int tileIsPixel:1; /* tile is solid pixel */ + unsigned int fExpose:1; /* Call exposure handling */ + unsigned int freeCompClip:1; /* Free composite clip */ + unsigned int unused:14; /* see comment above */ + unsigned long planemask; + unsigned long fgPixel; + unsigned long bgPixel; + /* + * alas -- both tile and stipple must be here as they + * are independently specifiable + */ + PixUnion tile; + PixmapPtr stipple; + DDXPointRec patOrg; /* origin for (tile, stipple) */ + struct _Font *font; + DDXPointRec clipOrg; + DDXPointRec lastWinOrg; /* position of window last validated */ + pointer clientClip; + unsigned long stateChanges; /* masked with GC_ */ + unsigned long serialNumber; + const GCFuncs *funcs; + GCOps *ops; + DevUnion *devPrivates; + /* + * The following were moved here from private storage to allow device- + * independent access to them from screen wrappers. + * --- 1997.11.03 Marc Aurele La France (tsi@xfree86.org) + */ + PixmapPtr pRotatedPixmap; /* tile/stipple rotated for alignment */ + RegionPtr pCompositeClip; + /* fExpose & freeCompClip defined above */ +} GC; + +#endif /* GCSTRUCT_H */ diff --git a/include/globals.h b/include/globals.h new file mode 100644 index 0000000..fedb2cf --- /dev/null +++ b/include/globals.h @@ -0,0 +1,82 @@ + +#ifndef _XSERV_GLOBAL_H_ +#define _XSERV_GLOBAL_H_ + +#include "window.h" /* for WindowPtr */ + +/* Global X server variables that are visible to mi, dix, os, and ddx */ + +extern CARD32 defaultScreenSaverTime; +extern CARD32 defaultScreenSaverInterval; +extern CARD32 ScreenSaverTime; +extern CARD32 ScreenSaverInterval; + +#ifdef SCREENSAVER +extern Bool screenSaverSuspended; +#endif + +extern char *defaultFontPath; +extern int monitorResolution; +extern int defaultColorVisualClass; + +extern Bool Must_have_memory; +extern WindowPtr WindowTable[MAXSCREENS]; +extern int GrabInProgress; +extern Bool noTestExtensions; + +extern DDXPointRec dixScreenOrigins[MAXSCREENS]; + +#ifdef DPMSExtension +extern CARD32 DPMSStandbyTime; +extern CARD32 DPMSSuspendTime; +extern CARD32 DPMSOffTime; +extern CARD16 DPMSPowerLevel; +extern Bool DPMSEnabled; +extern Bool DPMSEnabledSwitch; +extern Bool DPMSDisabledSwitch; +extern Bool DPMSCapableFlag; +#endif + +extern Bool noBigReqExtension; + +extern Bool noDamageExtension; + +#ifdef DBE +extern Bool noDbeExtension; +#endif + +#ifdef DPMSExtension +extern Bool noDPMSExtension; +#endif + + +#ifdef SCREENSAVER +extern Bool noScreenSaverExtension; +#endif + +extern Bool noMITShmExtension; + + +extern Bool noRRExtension; + +extern Bool noRenderExtension; + +extern Bool noShapeExtension; + +extern Bool noSyncExtension; + +#ifdef RES +extern Bool noResExtension; +#endif + +#ifdef XF86BIGFONT +extern Bool noXFree86BigfontExtension; +#endif + + + + +extern Bool noXFixesExtension; + + +#endif /* !_XSERV_GLOBAL_H_ */ diff --git a/include/input.h b/include/input.h new file mode 100644 index 0000000..297f5fc --- /dev/null +++ b/include/input.h @@ -0,0 +1,333 @@ +/************************************************************ + +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. + +********************************************************/ + +#ifndef INPUT_H +#define INPUT_H + +#include "misc.h" +#include "screenint.h" +#include +#include +#include "window.h" /* for WindowPtr */ + +#define DEVICE_INIT 0 +#define DEVICE_ON 1 +#define DEVICE_OFF 2 +#define DEVICE_CLOSE 3 + +#define MAP_LENGTH 256 +#define DOWN_LENGTH 32 /* 256/8 => number of bytes to hold 256 bits */ +#define NullGrab ((GrabPtr)NULL) +#define PointerRootWin ((WindowPtr)PointerRoot) +#define NoneWin ((WindowPtr)None) +#define NullDevice ((DevicePtr)NULL) + +#ifndef FollowKeyboard +#define FollowKeyboard 3 +#endif +#ifndef FollowKeyboardWin +#define FollowKeyboardWin ((WindowPtr) FollowKeyboard) +#endif +#ifndef RevertToFollowKeyboard +#define RevertToFollowKeyboard 3 +#endif + +typedef unsigned long Leds; +typedef struct _OtherClients *OtherClientsPtr; +typedef struct _InputClients *InputClientsPtr; +typedef struct _DeviceIntRec *DeviceIntPtr; + +typedef int (*DeviceProc)( + DeviceIntPtr /*device*/, + int /*what*/); + +typedef void (*ProcessInputProc)( + xEventPtr /*events*/, + DeviceIntPtr /*device*/, + int /*count*/); + +typedef Bool (*DeviceHandleProc)( + DeviceIntPtr /*device*/, + void* /*data*/ + ); + +typedef void (*DeviceUnwrapProc)( + DeviceIntPtr /*device*/, + DeviceHandleProc /*proc*/, + void* /*data*/ + ); + +typedef struct _DeviceRec { + pointer devicePrivate; + ProcessInputProc processInputProc; /* current */ + ProcessInputProc realInputProc; /* deliver */ + ProcessInputProc enqueueInputProc; /* enqueue */ + Bool on; /* used by DDX to keep state */ +} DeviceRec, *DevicePtr; + +typedef struct { + int click, bell, bell_pitch, bell_duration; + Bool autoRepeat; + unsigned char autoRepeats[32]; + Leds leds; + unsigned char id; +} KeybdCtrl; + +typedef struct { + KeySym *map; + KeyCode minKeyCode, + maxKeyCode; + int mapWidth; +} KeySymsRec, *KeySymsPtr; + +typedef struct { + int num, den, threshold; + unsigned char id; +} PtrCtrl; + +typedef struct { + int resolution, min_value, max_value; + int integer_displayed; + unsigned char id; +} IntegerCtrl; + +typedef struct { + int max_symbols, num_symbols_supported; + int num_symbols_displayed; + KeySym *symbols_supported; + KeySym *symbols_displayed; + unsigned char id; +} StringCtrl; + +typedef struct { + int percent, pitch, duration; + unsigned char id; +} BellCtrl; + +typedef struct { + Leds led_values; + Mask led_mask; + unsigned char id; +} LedCtrl; + +void ResetDevicePrivateIndex(void); + +extern KeybdCtrl defaultKeyboardControl; +extern PtrCtrl defaultPointerControl; + +DeviceIntPtr AddInputDevice( + DeviceProc /*deviceProc*/, + Bool /*autoStart*/); + +Bool EnableDevice( + DeviceIntPtr /*device*/); + +Bool DisableDevice( + DeviceIntPtr /*device*/); + +int InitAndStartDevices(void); + +void CloseDownDevices(void); + +void RemoveDevice( + DeviceIntPtr /*dev*/); + +int NumMotionEvents(void); + +void RegisterPointerDevice( + DeviceIntPtr /*device*/); + +void RegisterKeyboardDevice( + DeviceIntPtr /*device*/); + +DevicePtr LookupKeyboardDevice(void); + +DevicePtr LookupPointerDevice(void); + +DevicePtr LookupDevice( + int /* id */); + +void QueryMinMaxKeyCodes( + KeyCode* /*minCode*/, + KeyCode* /*maxCode*/); + +Bool SetKeySymsMap( + KeySymsPtr /*dst*/, + KeySymsPtr /*src*/); + +Bool InitKeyClassDeviceStruct( + DeviceIntPtr /*device*/, + KeySymsPtr /*pKeySyms*/, + CARD8 /*pModifiers*/[]); + +Bool InitButtonClassDeviceStruct( + DeviceIntPtr /*device*/, + int /*numButtons*/, + CARD8* /*map*/); + +typedef int (*ValuatorMotionProcPtr)( + DeviceIntPtr /*pdevice*/, + xTimecoord * /*coords*/, + unsigned long /*start*/, + unsigned long /*stop*/, + ScreenPtr /*pScreen*/); + +Bool InitValuatorClassDeviceStruct( + DeviceIntPtr /*device*/, + int /*numAxes*/, + ValuatorMotionProcPtr /* motionProc */, + int /*numMotionEvents*/, + int /*mode*/); + +Bool InitFocusClassDeviceStruct( + DeviceIntPtr /*device*/); + +typedef void (*BellProcPtr)( + int /*percent*/, + DeviceIntPtr /*device*/, + pointer /*ctrl*/, + int); + +typedef void (*KbdCtrlProcPtr)( + DeviceIntPtr /*device*/, + KeybdCtrl * /*ctrl*/); + +Bool InitKbdFeedbackClassDeviceStruct( + DeviceIntPtr /*device*/, + BellProcPtr /*bellProc*/, + KbdCtrlProcPtr /*controlProc*/); + +typedef void (*PtrCtrlProcPtr)( + DeviceIntPtr /*device*/, + PtrCtrl * /*ctrl*/); + +Bool InitPtrFeedbackClassDeviceStruct( + DeviceIntPtr /*device*/, + PtrCtrlProcPtr /*controlProc*/); + +typedef void (*StringCtrlProcPtr)( + DeviceIntPtr /*device*/, + StringCtrl * /*ctrl*/); + +typedef void (*BellCtrlProcPtr)( + DeviceIntPtr /*device*/, + BellCtrl * /*ctrl*/); + +typedef void (*LedCtrlProcPtr)( + DeviceIntPtr /*device*/, + LedCtrl * /*ctrl*/); + +typedef void (*IntegerCtrlProcPtr)( + DeviceIntPtr /*device*/, + IntegerCtrl * /*ctrl*/); + +Bool InitPointerDeviceStruct( + DevicePtr /*device*/, + CARD8* /*map*/, + int /*numButtons*/, + ValuatorMotionProcPtr /*motionProc*/, + PtrCtrlProcPtr /*controlProc*/, + int /*numMotionEvents*/); + +Bool InitKeyboardDeviceStruct( + DevicePtr /*device*/, + KeySymsPtr /*pKeySyms*/, + CARD8 /*pModifiers*/[], + BellProcPtr /*bellProc*/, + KbdCtrlProcPtr /*controlProc*/); + +void SendMappingNotify( + unsigned int /*request*/, + unsigned int /*firstKeyCode*/, + unsigned int /*count*/, + ClientPtr /* client */); + +Bool BadDeviceMap( + BYTE* /*buff*/, + int /*length*/, + unsigned /*low*/, + unsigned /*high*/, + XID* /*errval*/); + +Bool AllModifierKeysAreUp( + DeviceIntPtr /*device*/, + CARD8* /*map1*/, + int /*per1*/, + CARD8* /*map2*/, + int /*per2*/); + +void NoteLedState( + DeviceIntPtr /*keybd*/, + int /*led*/, + Bool /*on*/); + +void MaybeStopHint( + DeviceIntPtr /*device*/, + ClientPtr /*client*/); + +void ProcessPointerEvent( + xEventPtr /*xE*/, + DeviceIntPtr /*mouse*/, + int /*count*/); + +void ProcessKeyboardEvent( + xEventPtr /*xE*/, + DeviceIntPtr /*keybd*/, + int /*count*/); + + +Bool LegalModifier( + unsigned int /*key*/, + DevicePtr /*pDev*/); + +void ProcessInputEvents(void); + +void InitInput( + int /*argc*/, + char ** /*argv*/); + +#endif /* INPUT_H */ diff --git a/include/inputstr.h b/include/inputstr.h new file mode 100644 index 0000000..490ad39 --- /dev/null +++ b/include/inputstr.h @@ -0,0 +1,297 @@ +/************************************************************ + +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. + +********************************************************/ + + +#ifndef INPUTSTRUCT_H +#define INPUTSTRUCT_H + +#include "input.h" +#include "window.h" +#include "dixstruct.h" + +#define BitIsOn(ptr, bit) (((BYTE *) (ptr))[(bit)>>3] & (1 << ((bit) & 7))) + +#define SameClient(obj,client) \ + (CLIENT_BITS((obj)->resource) == (client)->clientAsMask) + +#define MAX_DEVICES 20 + +#define EMASKSIZE MAX_DEVICES + +/* Kludge: OtherClients and InputClients must be compatible, see code */ + +typedef struct _OtherClients { + OtherClientsPtr next; + XID resource; /* id for putting into resource manager */ + Mask mask; +} OtherClients; + +typedef struct _InputClients { + InputClientsPtr next; + XID resource; /* id for putting into resource manager */ + Mask mask[EMASKSIZE]; +} InputClients; + +typedef struct _OtherInputMasks { + Mask deliverableEvents[EMASKSIZE]; + Mask inputEvents[EMASKSIZE]; + Mask dontPropagateMask[EMASKSIZE]; + InputClientsPtr inputClients; +} OtherInputMasks; + +/* + * The following structure gets used for both active and passive grabs. For + * active grabs some of the fields (e.g. modifiers) are not used. However, + * that is not much waste since there aren't many active grabs (one per + * keyboard/pointer device) going at once in the server. + */ + +#define MasksPerDetailMask 8 /* 256 keycodes and 256 possible + modifier combinations, but only + 3 buttons. */ + + typedef struct _DetailRec { /* Grab details may be bit masks */ + unsigned short exact; + Mask *pMask; + } DetailRec; + + typedef struct _GrabRec { + GrabPtr next; /* for chain of passive grabs */ + XID resource; + DeviceIntPtr device; + WindowPtr window; + unsigned ownerEvents:1; + unsigned keyboardMode:1; + unsigned pointerMode:1; + unsigned coreGrab:1; /* grab is on core device */ + unsigned coreMods:1; /* modifiers are on core keyboard */ + CARD8 type; /* event type */ + DetailRec modifiersDetail; + DeviceIntPtr modifierDevice; + DetailRec detail; /* key or button */ + WindowPtr confineTo; /* always NULL for keyboards */ + CursorPtr cursor; /* always NULL for keyboards */ + Mask eventMask; +} GrabRec; + +typedef struct _KeyClassRec { + CARD8 down[DOWN_LENGTH]; + KeyCode *modifierKeyMap; + KeySymsRec curKeySyms; + int modifierKeyCount[8]; + CARD8 modifierMap[MAP_LENGTH]; + CARD8 maxKeysPerModifier; + unsigned short state; + unsigned short prev_state; +} KeyClassRec, *KeyClassPtr; + +typedef struct _AxisInfo { + int resolution; + int min_resolution; + int max_resolution; + int min_value; + int max_value; +} AxisInfo, *AxisInfoPtr; + +typedef struct _ValuatorClassRec { + ValuatorMotionProcPtr GetMotionProc; + int numMotionEvents; + WindowPtr motionHintWindow; + AxisInfoPtr axes; + unsigned short numAxes; + int *axisVal; + CARD8 mode; +} ValuatorClassRec, *ValuatorClassPtr; + +typedef struct _ButtonClassRec { + CARD8 numButtons; + CARD8 buttonsDown; /* number of buttons currently down */ + unsigned short state; + Mask motionMask; + CARD8 down[DOWN_LENGTH]; + CARD8 map[MAP_LENGTH]; +} ButtonClassRec, *ButtonClassPtr; + +typedef struct _FocusClassRec { + WindowPtr win; + int revert; + TimeStamp time; + WindowPtr *trace; + int traceSize; + int traceGood; +} FocusClassRec, *FocusClassPtr; + +typedef struct _ProximityClassRec { + char pad; +} ProximityClassRec, *ProximityClassPtr; + +typedef struct _KbdFeedbackClassRec *KbdFeedbackPtr; +typedef struct _PtrFeedbackClassRec *PtrFeedbackPtr; +typedef struct _IntegerFeedbackClassRec *IntegerFeedbackPtr; +typedef struct _StringFeedbackClassRec *StringFeedbackPtr; +typedef struct _BellFeedbackClassRec *BellFeedbackPtr; +typedef struct _LedFeedbackClassRec *LedFeedbackPtr; + +typedef struct _KbdFeedbackClassRec { + BellProcPtr BellProc; + KbdCtrlProcPtr CtrlProc; + KeybdCtrl ctrl; + KbdFeedbackPtr next; +} KbdFeedbackClassRec; + +typedef struct _PtrFeedbackClassRec { + PtrCtrlProcPtr CtrlProc; + PtrCtrl ctrl; + PtrFeedbackPtr next; +} PtrFeedbackClassRec; + +typedef struct _IntegerFeedbackClassRec { + IntegerCtrlProcPtr CtrlProc; + IntegerCtrl ctrl; + IntegerFeedbackPtr next; +} IntegerFeedbackClassRec; + +typedef struct _StringFeedbackClassRec { + StringCtrlProcPtr CtrlProc; + StringCtrl ctrl; + StringFeedbackPtr next; +} StringFeedbackClassRec; + +typedef struct _BellFeedbackClassRec { + BellProcPtr BellProc; + BellCtrlProcPtr CtrlProc; + BellCtrl ctrl; + BellFeedbackPtr next; +} BellFeedbackClassRec; + +typedef struct _LedFeedbackClassRec { + LedCtrlProcPtr CtrlProc; + LedCtrl ctrl; + LedFeedbackPtr next; +} LedFeedbackClassRec; + +/* states for devices */ + +#define NOT_GRABBED 0 +#define THAWED 1 +#define THAWED_BOTH 2 /* not a real state */ +#define FREEZE_NEXT_EVENT 3 +#define FREEZE_BOTH_NEXT_EVENT 4 +#define FROZEN 5 /* any state >= has device frozen */ +#define FROZEN_NO_EVENT 5 +#define FROZEN_WITH_EVENT 6 +#define THAW_OTHERS 7 + +typedef struct _DeviceIntRec { + DeviceRec public; + DeviceIntPtr next; + TimeStamp grabTime; + Bool startup; /* true if needs to be turned on at + server intialization time */ + DeviceProc deviceProc; /* proc(DevicePtr, DEVICE_xx). It is + used to initialize, turn on, or + turn off the device */ + Bool inited; /* TRUE if INIT returns Success */ + GrabPtr grab; /* the grabber - used by DIX */ + struct { + Bool frozen; + int state; + GrabPtr other; /* if other grab has this frozen */ + xEvent *event; /* saved to be replayed */ + int evcount; + } sync; + Atom type; + char *name; + CARD8 id; + CARD8 activatingKey; + Bool fromPassiveGrab; + GrabRec activeGrab; + void (*ActivateGrab) ( + DeviceIntPtr /*device*/, + GrabPtr /*grab*/, + TimeStamp /*time*/, + Bool /*autoGrab*/); + void (*DeactivateGrab)( + DeviceIntPtr /*device*/); + KeyClassPtr key; + ValuatorClassPtr valuator; + ButtonClassPtr button; + FocusClassPtr focus; + ProximityClassPtr proximity; + KbdFeedbackPtr kbdfeed; + PtrFeedbackPtr ptrfeed; + IntegerFeedbackPtr intfeed; + StringFeedbackPtr stringfeed; + BellFeedbackPtr bell; + LedFeedbackPtr leds; + DevUnion *devPrivates; + int nPrivates; + DeviceUnwrapProc unwrapProc; +} DeviceIntRec; + +typedef struct { + int numDevices; /* total number of devices */ + DeviceIntPtr devices; /* all devices turned on */ + DeviceIntPtr off_devices; /* all devices turned off */ + DeviceIntPtr keyboard; /* the main one for the server */ + DeviceIntPtr pointer; +} InputInfo; + +extern InputInfo inputInfo; + +/* for keeping the events for devices grabbed synchronously */ +typedef struct _QdEvent *QdEventPtr; +typedef struct _QdEvent { + QdEventPtr next; + DeviceIntPtr device; + ScreenPtr pScreen; /* what screen the pointer was on */ + unsigned long months; /* milliseconds is in the event */ + xEvent *event; + int evcount; +} QdEventRec; + +#endif /* INPUTSTRUCT_H */ diff --git a/include/kdrive-config.h.in b/include/kdrive-config.h.in new file mode 100644 index 0000000..07b5b4b --- /dev/null +++ b/include/kdrive-config.h.in @@ -0,0 +1,21 @@ +/* kdrive-config.h.in: not at all generated. -*- c -*- + */ + +#ifndef _KDRIVE_CONFIG_H_ +#define _KDRIVE_CONFIG_H_ + +#include + +/* Building kdrive server. */ +#undef KDRIVESERVER + +/* Include framebuffer support in X servers */ +#undef KDRIVEFBDEV + +/* Include vesa support in X servers */ +#undef KDRIVEVESA + +/* Verbose debugging output hilarity */ +#undef DEBUG + +#endif /* _KDRIVE_CONFIG_H_ */ diff --git a/include/misc.h b/include/misc.h new file mode 100644 index 0000000..0f59812 --- /dev/null +++ b/include/misc.h @@ -0,0 +1,298 @@ +/*********************************************************** + +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. + +Copyright 1992, 1993 Data General Corporation; +Copyright 1992, 1993 OMRON Corporation + +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, and that +neither the name OMRON or DATA GENERAL be used in advertising or publicity +pertaining to distribution of the software without specific, written prior +permission of the party whose name is to be used. Neither OMRON or +DATA GENERAL make any representation about the suitability of this software +for any purpose. It is provided "as is" without express or implied warranty. + +OMRON AND DATA GENERAL EACH DISCLAIM ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, +IN NO EVENT SHALL OMRON OR DATA GENERAL BE LIABLE FOR ANY SPECIAL, INDIRECT +OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, +DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE +OF THIS SOFTWARE. + +******************************************************************/ +#ifndef MISC_H +#define MISC_H 1 +/* + * X internal definitions + * + */ + +extern unsigned long globalSerialNumber; +extern unsigned long serverGeneration; + +#include +#include +#include +#include +#include + +#include +#include + +#ifndef MAXSCREENS +#define MAXSCREENS 16 +#endif +#define MAXCLIENTS 256 +#define MAXDITS 1 +#define MAXEXTENSIONS 128 +#define MAXFORMATS 8 +#define MAXVISUALS_PER_SCREEN 50 + +typedef unsigned long PIXEL; +typedef unsigned long ATOM; + + +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif + +#ifndef _XTYPEDEF_CALLBACKLISTPTR +typedef struct _CallbackList *CallbackListPtr; /* also in dix.h */ +#define _XTYPEDEF_CALLBACKLISTPTR +#endif + +typedef struct _xReq *xReqPtr; + +#include "os.h" /* for ALLOCATE_LOCAL and DEALLOCATE_LOCAL */ +#include /* for bcopy, bzero, and bcmp */ + +#define NullBox ((BoxPtr)0) +#define MILLI_PER_MIN (1000 * 60) +#define MILLI_PER_SECOND (1000) + + /* this next is used with None and ParentRelative to tell + PaintWin() what to use to paint the background. Also used + in the macro IS_VALID_PIXMAP */ + +#define USE_BACKGROUND_PIXEL 3 +#define USE_BORDER_PIXEL 3 + + +/* byte swap a 32-bit literal */ +static inline uint32_t lswapl(uint32_t x) +{ + return ((x & 0xff) << 24) | + ((x & 0xff00) << 8) | + ((x & 0xff0000) >> 8) | + ((x >> 24) & 0xff); +} + +/* byte swap a 16-bit literal */ +static inline uint16_t lswaps(uint16_t x) +{ + return ((x & 0xff) << 8) | ((x >> 8) & 0xff); +} + +#undef min +#undef max + +#define min(a, b) (((a) < (b)) ? (a) : (b)) +#define max(a, b) (((a) > (b)) ? (a) : (b)) +/* abs() is a function, not a macro; include the file declaring + * it in case we haven't done that yet. + */ +#include +#define sign(x) ((x) < 0 ? -1 : ((x) > 0 ? 1 : 0)) +/* this assumes b > 0 */ +#define modulus(a, b, d) if (((d) = (a) % (b)) < 0) (d) += (b) +/* + * return the least significant bit in x which is set + * + * This works on 1's complement and 2's complement machines. + * If you care about the extra instruction on 2's complement + * machines, change to ((x) & (-(x))) + */ +#define lowbit(x) ((x) & (~(x) + 1)) + +/* XXX Not for modules */ +#include +#if !defined(MAXSHORT) || !defined(MINSHORT) || \ + !defined(MAXINT) || !defined(MININT) +/* + * Some implementations #define these through , so preclude + * #include'ing it later. + */ + +#include +#undef MAXSHORT +#define MAXSHORT SHRT_MAX +#undef MINSHORT +#define MINSHORT SHRT_MIN +#undef MAXINT +#define MAXINT INT_MAX +#undef MININT +#define MININT INT_MIN + +#include +#include +#include /* for fopen, etc... */ + +#endif + +/* some macros to help swap requests, replies, and events */ + +#define LengthRestB(stuff) \ + ((client->req_len << 2) - sizeof(*stuff)) + +#define LengthRestS(stuff) \ + ((client->req_len << 1) - (sizeof(*stuff) >> 1)) + +#define LengthRestL(stuff) \ + (client->req_len - (sizeof(*stuff) >> 2)) + +#define SwapRestS(stuff) \ + SwapShorts((short *)(stuff + 1), LengthRestS(stuff)) + +#define SwapRestL(stuff) \ + SwapLongs((CARD32 *)(stuff + 1), LengthRestL(stuff)) + +#ifdef __GNUC__ +void wrong_size(void); +#else +static inline void wrong_size(void) +{ +} + +static inline void __builtin_constant_p(int x) +{ + return 0; +} +#endif + +/* byte swap a 32-bit value */ +static inline void swap_uint32(uint32_t *x) +{ + char n = ((char *) &x)[0]; + ((char *) x)[0] = ((char *) x)[3]; + ((char *) x)[3] = n; + n = ((char *) x)[1]; + ((char *) x)[1] = ((char *) x)[2]; + ((char *) x)[2] = n; +} + +#define swapl(x) do { \ + if (sizeof(*(x)) != 4) \ + wrong_size(); \ + if (__builtin_constant_p((uintptr_t)(x) & 3) && ((uintptr_t)(x) & 3) == 0) \ + *(x) = lswapl(*(x)); \ + else \ + swap_uint32((uint32_t *)(x)); \ + } while (0) + +/* byte swap a 16-bit value */ +static inline void swap_uint16(uint16_t *x) +{ + char n = ((char *) x)[0]; + ((char *) x)[0] = ((char *) x)[1]; + ((char *) x)[1] = n; +} + +#define swaps(x) do { \ + if (sizeof(*(x)) != 2) \ + wrong_size(); \ + if (__builtin_constant_p((uintptr_t)(x) & 1) && ((uintptr_t)(x) & 1) == 0) \ + *(x) = lswaps(*(x)); \ + else \ + swap_uint16((uint16_t *)(x)); \ + } while (0) + +/* copy 32-bit value from src to dst byteswapping on the way */ +#define cpswapl(src, dst) do { \ + if (sizeof((src)) != 4 || sizeof((dst)) != 4) \ + wrong_size(); \ + (dst) = lswapl((src)); \ + } while (0) + +/* copy short from src to dst byteswapping on the way */ +#define cpswaps(src, dst) do { \ + if (sizeof((src)) != 2 || sizeof((dst)) != 2) \ + wrong_size(); \ + (dst) = lswaps((src)); \ + } while (0) + +void SwapLongs( + CARD32 *list, + unsigned long count); + +void SwapShorts( + short *list, + unsigned long count); + +void MakePredeclaredAtoms(void); + +int Ones( + unsigned long /*mask*/); + +typedef struct _xPoint *DDXPointPtr; +typedef struct _Box *BoxPtr; +typedef struct _xEvent *xEventPtr; +typedef struct _xRectangle *xRectanglePtr; +typedef struct _GrabRec *GrabPtr; + +/* typedefs from other places - duplicated here to minimize the amount + * of unnecessary junk that one would normally have to include to get + * these symbols defined + */ + +#ifndef _XTYPEDEF_CHARINFOPTR +typedef struct _CharInfo *CharInfoPtr; /* also in fonts/include/font.h */ +#define _XTYPEDEF_CHARINFOPTR +#endif + +#endif /* MISC_H */ diff --git a/include/miscstruct.h b/include/miscstruct.h new file mode 100644 index 0000000..1ecbb33 --- /dev/null +++ b/include/miscstruct.h @@ -0,0 +1,78 @@ +/*********************************************************** + +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. + +******************************************************************/ + +#ifndef MISCSTRUCT_H +#define MISCSTRUCT_H 1 + +#include "misc.h" +#include +#include "gc.h" + +typedef xPoint DDXPointRec; + +typedef struct _Box { + short x1, y1, x2, y2; +} BoxRec; + +typedef union _DevUnion { + pointer ptr; + long val; + unsigned long uval; + RegionPtr (*fptr)( + DrawablePtr /* pSrcDrawable */, + DrawablePtr /* pDstDrawable */, + GCPtr /* pGC */, + int /* srcx */, + int /* srcy */, + int /* width */, + int /* height */, + int /* dstx */, + int /* dsty */, + unsigned long /* bitPlane */); +} DevUnion; + +#endif /* MISCSTRUCT_H */ diff --git a/include/opaque.h b/include/opaque.h new file mode 100644 index 0000000..9743a8f --- /dev/null +++ b/include/opaque.h @@ -0,0 +1,75 @@ +/* + +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. + +*/ + +#ifndef OPAQUE_H +#define OPAQUE_H + +#include + +#include "globals.h" + +extern char *defaultTextFont; +extern char *defaultCursorFont; +extern int MaxClients; +extern volatile char isItTimeToYield; +extern volatile char dispatchException; + +/* bit values for dispatchException */ +#define DE_RESET 1 +#define DE_TERMINATE 2 +#define DE_PRIORITYCHANGE 4 /* set when a client's priority changes */ + +extern CARD32 TimeOutValue; +extern int ScreenSaverBlanking; +extern int ScreenSaverAllowExposures; +extern int defaultScreenSaverBlanking; +extern int defaultScreenSaverAllowExposures; +extern char *display; + +extern Bool PartialNetwork; +#ifndef NOLOGOHACK +extern int logoScreenSaver; +#endif +#ifdef RLIMIT_DATA +extern int limitDataSpace; +#endif +#ifdef RLIMIT_STACK +extern int limitStackSpace; +#endif +#ifdef RLIMIT_NOFILE +extern int limitNoFile; +#endif +extern Bool defeatAccessControl; +extern long maxBigRequestSize; +extern Bool blackRoot; +extern Bool whiteRoot; + +extern Bool CoreDump; + + +#endif /* OPAQUE_H */ diff --git a/include/os.h b/include/os.h new file mode 100644 index 0000000..805f748 --- /dev/null +++ b/include/os.h @@ -0,0 +1,407 @@ +/*********************************************************** + +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. + +******************************************************************/ + + +#ifndef OS_H +#define OS_H + +#include "misc.h" +#include +#include + +#define NullFID ((FID) 0) + +#define SCREEN_SAVER_OFF 0 +#define SCREEN_SAVER_ON 1 +#define SCREEN_SAVER_FORCER 2 +#define SCREEN_SAVER_CYCLE 3 + +#ifndef MAX_REQUEST_SIZE +#define MAX_REQUEST_SIZE 65535 +#endif +#ifndef MAX_BIG_REQUEST_SIZE +#define MAX_BIG_REQUEST_SIZE 4194303 +#endif + +typedef pointer FID; +typedef struct _FontPathRec *FontPathPtr; +typedef struct _NewClientRec *NewClientPtr; + +#include +#include + +/* have to put $(SIGNAL_DEFINES) in DEFINES in Imakefile to get this right */ +#ifdef SIGNALRETURNSINT +#define SIGVAL int +#else +#define SIGVAL void +#endif + +void (*OsVendorVErrorFProc)(const char *, va_list args); + +int WaitForSomething( + int* /*pClientsReady*/ +); + +int ReadRequestFromClient(ClientPtr /*client*/); + +Bool InsertFakeRequest( + ClientPtr /*client*/, + char* /*data*/, + int /*count*/); + +void ResetCurrentRequest(ClientPtr /*client*/); + +void FlushAllOutput(void); + +void FlushIfCriticalOutputPending(void); + +void SetCriticalOutputPending(void); + +int WriteToClient(ClientPtr /*who*/, int /*count*/, const char* /*buf*/); + +void ResetOsBuffers(void); + +void InitConnectionLimits(void); + +void CreateWellKnownSockets(void); + +void ResetWellKnownSockets(void); + +void CloseWellKnownConnections(void); + +const char *ClientAuthorized( + ClientPtr /*client*/, + unsigned int /*proto_n*/, + char* /*auth_proto*/, + unsigned int /*string_n*/, + char* /*auth_string*/); + +Bool EstablishNewConnections( + ClientPtr /*clientUnused*/, + pointer /*closure*/); + +void CheckConnections(void); + +void CloseDownConnection(ClientPtr /*client*/); + +void AddGeneralSocket(int /*fd*/); + +void RemoveGeneralSocket(int /*fd*/); + +void AddEnabledDevice(int /*fd*/); + +void RemoveEnabledDevice(int /*fd*/); + +void OnlyListenToOneClient(ClientPtr /*client*/); + +void ListenToAllClients(void); + +void IgnoreClient(ClientPtr /*client*/); + +void AttendClient(ClientPtr /*client*/); + +void MakeClientGrabImpervious(ClientPtr /*client*/); + +void MakeClientGrabPervious(ClientPtr /*client*/); + +void AvailableClientInput(ClientPtr /* client */); + +CARD32 GetTimeInMillis(void); + +void AdjustWaitForDelay( + pointer /*waitTime*/, + unsigned long /*newdelay*/); + +typedef struct _OsTimerRec *OsTimerPtr; + +typedef CARD32 (*OsTimerCallback)( + OsTimerPtr /* timer */, + CARD32 /* time */, + pointer /* arg */); + +void TimerInit(void); + +Bool TimerForce(OsTimerPtr /* timer */); + +#define TimerAbsolute (1<<0) +#define TimerForceOld (1<<1) + +OsTimerPtr TimerSet( + OsTimerPtr /* timer */, + int /* flags */, + CARD32 /* millis */, + OsTimerCallback /* func */, + pointer /* arg */); + +void TimerCancel(OsTimerPtr /* pTimer */); +void TimerFree(OsTimerPtr /* pTimer */); + +void SetScreenSaverTimer(void); +void FreeScreenSaverTimer(void); + +SIGVAL AutoResetServer(int /*sig*/); + +SIGVAL GiveUp(int /*sig*/); + +void UseMsg(void); + +void ProcessCommandLine(int /*argc*/, char* /*argv*/[]); + +int set_font_authorizations( + char ** /* authorizations */, + int * /*authlen */, + pointer /* client */); + +void OsInitAllocator(void); + +typedef SIGVAL (*OsSigHandlerPtr)(int /* sig */); + +OsSigHandlerPtr OsSignal(int /* sig */, OsSigHandlerPtr /* handler */); + +extern int auditTrailLevel; + +void LockServer(void); +void UnlockServer(void); + +int OsLookupColor( + int /*screen*/, + char * /*name*/, + unsigned /*len*/, + unsigned short * /*pred*/, + unsigned short * /*pgreen*/, + unsigned short * /*pblue*/); + +void OsInit(void); + +void OsCleanup(Bool); + +void OsVendorFatalError(void); + +void OsVendorInit(void); + +void OsBlockSignals (void); + +void OsReleaseSignals (void); + +int System(char *); +pointer Popen(char *, char *); +int Pclose(pointer); +pointer Fopen(char *, char *); +int Fclose(pointer); + +void CheckUserParameters(int argc, char **argv, char **envp); +void CheckUserAuthorization(void); + +int AddHost( + ClientPtr /*client*/, + int /*family*/, + unsigned /*length*/, + const void * /*pAddr*/); + +int RemoveHost( + ClientPtr /*client*/, + int /*family*/, + unsigned /*length*/, + pointer /*pAddr*/); + +int GetHosts( + pointer * /*data*/, + int * /*pnHosts*/, + int * /*pLen*/, + BOOL * /*pEnabled*/); + +typedef struct sockaddr * sockaddrPtr; + +int InvalidHost(sockaddrPtr /*saddr*/, int /*len*/, ClientPtr client); + +int LocalClient(ClientPtr /* client */); + +int LocalClientCred(ClientPtr, int *, int *); + +int ChangeAccessControl(ClientPtr /*client*/, int /*fEnabled*/); + +void AddLocalHosts(void); + +void ResetHosts(char *display); + +void EnableLocalHost(void); + +void DisableLocalHost(void); + +void AccessUsingXdmcp(void); + +void DefineSelf(int /*fd*/); + +void AugmentSelf(pointer /*from*/, int /*len*/); + +void InitAuthorization(char * /*filename*/); + +/* int LoadAuthorization(void); */ + +void RegisterAuthorizations(void); + +XID CheckAuthorization( + unsigned int /*namelength*/, + const char * /*name*/, + unsigned int /*datalength*/, + const char * /*data*/, + ClientPtr /*client*/, + const char ** /*reason*/ +); + +void ResetAuthorization(void); + +int AddAuthorization( + unsigned int /*name_length*/, + const char * /*name*/, + unsigned int /*data_length*/, + char * /*data*/); + +XID GenerateAuthorization( + unsigned int /* name_length */, + char * /* name */, + unsigned int /* data_length */, + char * /* data */, + unsigned int * /* data_length_return */, + char ** /* data_return */); + + +int ddxProcessArgument(int /*argc*/, char * /*argv*/ [], int /*i*/); + +void ddxUseMsg(void); + +/* int ReqLen(xReq *req, ClientPtr client) + * Given a pointer to a *complete* request, return its length in bytes. + * Note that if the request is a big request (as defined in the Big + * Requests extension), the macro lies by returning 4 less than the + * length that it actually occupies in the request buffer. This is so you + * can blindly compare the length with the various sz_ constants + * in Xproto.h without having to know/care about big requests. + */ +#define ReqLen(_pxReq, _client) \ + ((_pxReq->length ? \ + (_client->swapped ? lswaps(_pxReq->length) : _pxReq->length) \ + : ((_client->swapped ? \ + lswapl(((CARD32*)_pxReq)[1]) : ((CARD32*)_pxReq)[1])-1) \ + ) << 2) + +/* otherReqTypePtr CastxReq(xReq *req, otherReqTypePtr) + * Cast the given request to one of type otherReqTypePtr to access + * fields beyond the length field. + */ +#define CastxReq(_pxReq, otherReqTypePtr) \ + (_pxReq->length ? (otherReqTypePtr)_pxReq \ + : (otherReqTypePtr)(((CARD32*)_pxReq)+1)) + +typedef struct { + xReqPtr req; + ClientPtr client; + int numskipped; +} SkippedRequestInfoRec; + +/* stuff for ReplyCallback */ +extern CallbackListPtr ReplyCallback; +typedef struct { + ClientPtr client; + const void * replyData; + unsigned long dataLenBytes; + unsigned long bytesRemaining; + Bool startOfReply; +} ReplyInfoRec; + +/* stuff for FlushCallback */ +extern CallbackListPtr FlushCallback; + +void AbortDDX(void); +void ddxGiveUp(void); +int TimeSinceLastInputEvent(void); + +/* Logging. */ +typedef enum _LogParameter { + XLOG_FLUSH, + XLOG_SYNC, + XLOG_VERBOSITY, + XLOG_FILE_VERBOSITY +} LogParameter; + +/* Flags for log messages. */ +typedef enum { + X_PROBED, /* Value was probed */ + X_CONFIG, /* Value was given in the config file */ + X_DEFAULT, /* Value is a default */ + X_CMDLINE, /* Value was given on the command line */ + X_NOTICE, /* Notice */ + X_ERROR, /* Error message */ + X_WARNING, /* Warning message */ + X_INFO, /* Informational message */ + X_NONE, /* No prefix */ + X_NOT_IMPLEMENTED, /* Not implemented */ + X_UNKNOWN = -1 /* unknown -- this must always be last */ +} MessageType; + +/* XXX Need to check which GCC versions have the format(printf) attribute. */ +#if defined(__GNUC__) && \ + ((__GNUC__ > 2) || ((__GNUC__ == 2) && (__GNUC_MINOR__ > 4))) +#define _printf_attribute(a,b) __attribute((format(__printf__,a,b))) +#else +#define _printf_attribute(a,b) /**/ +#endif + +void AuditF(const char *f, ...) _printf_attribute(1,2); +void VAuditF(const char *f, va_list args); +void FatalError(const char *f, ...) _printf_attribute(1,2) +#if defined(__GNUC__) && \ + ((__GNUC__ > 2) || ((__GNUC__ == 2) && (__GNUC_MINOR__ > 4))) +__attribute((noreturn)) +#endif +; + +void VErrorF(const char *f, va_list args); +void ErrorF(const char *f, ...) _printf_attribute(1,2); + +#endif /* OS_H */ diff --git a/include/pixmap.h b/include/pixmap.h new file mode 100644 index 0000000..02d0882 --- /dev/null +++ b/include/pixmap.h @@ -0,0 +1,108 @@ +/*********************************************************** + +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. + +******************************************************************/ + +#ifndef PIXMAP_H +#define PIXMAP_H + +#include "misc.h" +#include "screenint.h" + +/* types for Drawable */ +#define DRAWABLE_WINDOW 0 +#define DRAWABLE_PIXMAP 1 +#define UNDRAWABLE_WINDOW 2 +#define DRAWABLE_BUFFER 3 + +/* flags to PaintWindow() */ +#define PW_BACKGROUND 0 +#define PW_BORDER 1 + +#define NullPixmap ((PixmapPtr)0) + +typedef struct _Drawable *DrawablePtr; +typedef struct _Pixmap *PixmapPtr; + +typedef union _PixUnion { + PixmapPtr pixmap; + unsigned long pixel; +} PixUnion; + +#define SamePixUnion(a,b,isPixel)\ + ((isPixel) ? (a).pixel == (b).pixel : (a).pixmap == (b).pixmap) + +#define EqualPixUnion(as, a, bs, b) \ + ((as) == (bs) && (SamePixUnion (a, b, as))) + +#define OnScreenDrawable(type) \ + ((type == DRAWABLE_WINDOW) || (type == DRAWABLE_BUFFER)) + +#define WindowDrawable(type) \ + ((type == DRAWABLE_WINDOW) || (type == UNDRAWABLE_WINDOW)) + +PixmapPtr GetScratchPixmapHeader( + ScreenPtr /*pScreen*/, + int /*width*/, + int /*height*/, + int /*depth*/, + int /*bitsPerPixel*/, + int /*devKind*/, + pointer /*pPixData*/); + +void FreeScratchPixmapHeader( + PixmapPtr /*pPixmap*/); + +Bool CreateScratchPixmapsForScreen( + int /*scrnum*/); + +void FreeScratchPixmapsForScreen( + int /*scrnum*/); + +PixmapPtr AllocatePixmap( + ScreenPtr /*pScreen*/, + int /*pixDataSize*/); + +#endif /* PIXMAP_H */ diff --git a/include/pixmapstr.h b/include/pixmapstr.h new file mode 100644 index 0000000..a6bbb03 --- /dev/null +++ b/include/pixmapstr.h @@ -0,0 +1,91 @@ +/*********************************************************** + +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. + +******************************************************************/ + +#ifndef PIXMAPSTRUCT_H +#define PIXMAPSTRUCT_H +#include +#include "pixmap.h" +#include "screenint.h" +#include "regionstr.h" + +/* + * The padN members are unfortunate ABI BC. See fdo bug #6924. + */ + +typedef struct _Drawable { + unsigned char type; /* DRAWABLE_ */ + unsigned char class; /* specific to type */ + unsigned char depth; + unsigned char bitsPerPixel; +#if defined(_XSERVER64) + XID pad0; +#endif + XID id; /* resource id */ +#if defined(_XSERVER64) + XID pad1; +#endif + short x; /* window: screen absolute, pixmap: 0 */ + short y; /* window: screen absolute, pixmap: 0 */ + unsigned short width; + unsigned short height; + ScreenPtr pScreen; + unsigned long serialNumber; +} DrawableRec; + +/* + * PIXMAP -- device dependent + */ + +typedef struct _Pixmap { + DrawableRec drawable; + int refcnt; + int devKind; + DevUnion devPrivate; + DevUnion *devPrivates; /* real devPrivates like gcs & windows */ +} PixmapRec; + +#endif /* PIXMAPSTRUCT_H */ diff --git a/include/property.h b/include/property.h new file mode 100644 index 0000000..3b46f7e --- /dev/null +++ b/include/property.h @@ -0,0 +1,72 @@ +/*********************************************************** + +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. + +******************************************************************/ + +#ifndef PROPERTY_H +#define PROPERTY_H + +#include "window.h" + +typedef struct _Property *PropertyPtr; + +int ChangeWindowProperty( + WindowPtr /*pWin*/, + Atom /*property*/, + Atom /*type*/, + int /*format*/, + int /*mode*/, + unsigned long /*len*/, + pointer /*value*/, + Bool /*sendevent*/); + +int DeleteProperty( + WindowPtr /*pWin*/, + Atom /*propName*/); + +void DeleteAllWindowProperties( + WindowPtr /*pWin*/); + +#endif /* PROPERTY_H */ diff --git a/include/propertyst.h b/include/propertyst.h new file mode 100644 index 0000000..07ba385 --- /dev/null +++ b/include/propertyst.h @@ -0,0 +1,66 @@ +/*********************************************************** + +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. + +******************************************************************/ + +#ifndef PROPERTYSTRUCT_H +#define PROPERTYSTRUCT_H +#include "misc.h" +#include "property.h" +/* + * PROPERTY -- property element + */ + +typedef struct _Property { + struct _Property *next; + ATOM propertyName; + ATOM type; /* ignored by server */ + short format; /* format of data for swapping - 8,16,32 */ + long size; /* size of data in (format/8) bytes */ + pointer data; /* private to client */ +} PropertyRec; + +#endif /* PROPERTYSTRUCT_H */ + diff --git a/include/region.h b/include/region.h new file mode 100644 index 0000000..9bed139 --- /dev/null +++ b/include/region.h @@ -0,0 +1,53 @@ +/*********************************************************** + +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. + +******************************************************************/ + +#ifndef REGION_H +#define REGION_H + +#include "regionstr.h" + +#endif /* REGION_H */ diff --git a/include/regionstr.h b/include/regionstr.h new file mode 100644 index 0000000..7d7e2a5 --- /dev/null +++ b/include/regionstr.h @@ -0,0 +1,266 @@ +/*********************************************************** + +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. + +******************************************************************/ + +#ifndef REGIONSTRUCT_H +#define REGIONSTRUCT_H + +typedef struct _Region RegionRec, *RegionPtr; + +#include "miscstruct.h" + +/* Return values from RectIn() */ + +#define rgnOUT 0 +#define rgnIN 1 +#define rgnPART 2 + +#define NullRegion ((RegionPtr)0) + +/* + * clip region + */ + +typedef struct _RegData { + long size; + long numRects; +/* BoxRec rects[size]; in memory but not explicitly declared */ +} RegDataRec, *RegDataPtr; + +struct _Region { + BoxRec extents; + RegDataPtr data; +}; + +extern BoxRec miEmptyBox; +extern RegDataRec miEmptyData; +extern RegDataRec miBrokenData; + +#define REGION_NIL(reg) ((reg)->data && !(reg)->data->numRects) +/* not a region */ +#define REGION_NAR(reg) ((reg)->data == &miBrokenData) +#define REGION_NUM_RECTS(reg) ((reg)->data ? (reg)->data->numRects : 1) +#define REGION_SIZE(reg) ((reg)->data ? (reg)->data->size : 0) +#define REGION_RECTS(reg) ((reg)->data ? (BoxPtr)((reg)->data + 1) \ + : &(reg)->extents) +#define REGION_BOXPTR(reg) ((BoxPtr)((reg)->data + 1)) +#define REGION_BOX(reg,i) (®ION_BOXPTR(reg)[i]) +#define REGION_TOP(reg) REGION_BOX(reg, (reg)->data->numRects) +#define REGION_END(reg) REGION_BOX(reg, (reg)->data->numRects - 1) +#define REGION_SZOF(n) (sizeof(RegDataRec) + ((n) * sizeof(BoxRec))) + +#define REGION_CREATE(_rect, _size) \ + miRegionCreate(_rect, _size) + +#define REGION_COPY(dst, src) \ + miRegionCopy(dst, src) + +#define REGION_DESTROY(_pReg) \ + miRegionDestroy(_pReg) + +#define REGION_INTERSECT(newReg, reg1, reg2) \ + miIntersect(newReg, reg1, reg2) + +#define REGION_UNION(newReg, reg1, reg2) \ + miUnion(newReg, reg1, reg2) + +#define REGION_SUBTRACT(newReg, reg1, reg2) \ + miSubtract(newReg, reg1, reg2) + +#define REGION_INVERSE(newReg, reg1, invRect) \ + miInverse(newReg, reg1, invRect) + +#define REGION_TRANSLATE(_pReg, _x, _y) \ + miTranslateRegion(_pReg, _x, _y) + +#define RECT_IN_REGION(_pReg, prect) \ + miRectIn(_pReg, prect) + +#define POINT_IN_REGION(_pReg, _x, _y, prect) \ + miPointInRegion(_pReg, _x, _y, prect) + +#define REGION_APPEND(dstrgn, rgn) \ + miRegionAppend(dstrgn, rgn) + +#define REGION_VALIDATE(badreg, pOverlap) \ + miRegionValidate(badreg, pOverlap) + +#define BITMAP_TO_REGION(_pScreen, pPix) \ + (*(_pScreen)->BitmapToRegion)(pPix) /* no mi version?! */ + +#define RECTS_TO_REGION(nrects, prect, ctype) \ + miRectsToRegion(nrects, prect, ctype) + +#define REGION_EQUAL(_pReg1, _pReg2) \ + miRegionEqual(_pReg1, _pReg2) + +#define REGION_BREAK(_pReg) \ + miRegionBreak(_pReg) + +static inline void REGION_INIT(RegionPtr _pReg, BoxPtr _rect, int _size) { + + if (_rect != NULL) + { + (_pReg)->extents = *(_rect); + (_pReg)->data = (RegDataPtr)NULL; + } + else + { + (_pReg)->extents = miEmptyBox; + if (((_size) > 1) && ((_pReg)->data = + (RegDataPtr)malloc(REGION_SZOF(_size)))) + { + (_pReg)->data->size = (_size); + (_pReg)->data->numRects = 0; + } + else + (_pReg)->data = &miEmptyData; + } +} + +#define REGION_UNINIT(_pReg) \ +{ \ + if ((_pReg)->data && (_pReg)->data->size && (_pReg)->data != (&miEmptyData)) { \ + free((_pReg)->data); \ + } \ + (_pReg)->data = NULL; \ +} + +#define REGION_RESET(_pReg, _pBox) \ +{ \ + (_pReg)->extents = *(_pBox); \ + REGION_UNINIT(_pReg); \ + (_pReg)->data = (RegDataPtr)NULL; \ +} + +#define REGION_NOTEMPTY(_pReg) \ + !REGION_NIL(_pReg) + +#define REGION_BROKEN(_pReg) \ + REGION_NAR(_pReg) + +#define REGION_EMPTY(_pReg) \ +{ \ + REGION_UNINIT(_pReg); \ + (_pReg)->extents.x2 = (_pReg)->extents.x1; \ + (_pReg)->extents.y2 = (_pReg)->extents.y1; \ + (_pReg)->data = &miEmptyData; \ +} + +#define REGION_EXTENTS(_pReg) \ + (&(_pReg)->extents) + +#define REGION_NULL(_pReg) \ +{ \ + (_pReg)->extents = miEmptyBox; \ + (_pReg)->data = &miEmptyData; \ +} + +/* moved from mi.h */ + +RegionPtr miRegionCreate( + BoxPtr /*rect*/, + int /*size*/); + +void miRegionDestroy( + RegionPtr /*pReg*/); + +Bool miRegionCopy( + RegionPtr /*dst*/, + RegionPtr /*src*/); + +Bool miIntersect( + RegionPtr /*newReg*/, + RegionPtr /*reg1*/, + RegionPtr /*reg2*/); + +Bool miUnion( + RegionPtr /*newReg*/, + RegionPtr /*reg1*/, + RegionPtr /*reg2*/); + +Bool miRegionAppend( + RegionPtr /*dstrgn*/, + RegionPtr /*rgn*/); + +Bool miRegionValidate( + RegionPtr /*badreg*/, + Bool * /*pOverlap*/); + +RegionPtr miRectsToRegion( + int /*nrects*/, + xRectanglePtr /*prect*/, + int /*ctype*/); + +Bool miSubtract( + RegionPtr /*regD*/, + RegionPtr /*regM*/, + RegionPtr /*regS*/); + +Bool miInverse( + RegionPtr /*newReg*/, + RegionPtr /*reg1*/, + BoxPtr /*invRect*/); + +int miRectIn( + RegionPtr /*region*/, + BoxPtr /*prect*/); + +void miTranslateRegion( + RegionPtr /*pReg*/, + int /*x*/, + int /*y*/); + +Bool miRegionBreak( + RegionPtr /*pReg*/); + +Bool miPointInRegion( + RegionPtr /*pReg*/, + int /*x*/, + int /*y*/, + BoxPtr /*box*/); + +#endif /* REGIONSTRUCT_H */ diff --git a/include/resource.h b/include/resource.h new file mode 100644 index 0000000..1375c31 --- /dev/null +++ b/include/resource.h @@ -0,0 +1,256 @@ +/*********************************************************** + +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. + +******************************************************************/ + +#ifndef RESOURCE_H +#define RESOURCE_H 1 +#include "misc.h" + +/***************************************************************** + * STUFF FOR RESOURCES + *****************************************************************/ + +/* classes for Resource routines */ + +typedef unsigned long RESTYPE; + +#define RC_VANILLA ((RESTYPE)0) +#define RC_CACHED ((RESTYPE)1<<31) +#define RC_DRAWABLE ((RESTYPE)1<<30) +/* Use class RC_NEVERRETAIN for resources that should not be retained + * regardless of the close down mode when the client dies. (A client's + * event selections on objects that it doesn't own are good candidates.) + * Extensions can use this too! + */ +#define RC_NEVERRETAIN ((RESTYPE)1<<29) +#define RC_LASTPREDEF RC_NEVERRETAIN +#define RC_ANY (~(RESTYPE)0) + +/* types for Resource routines */ + +#define RT_WINDOW ((RESTYPE)1|RC_CACHED|RC_DRAWABLE) +#define RT_PIXMAP ((RESTYPE)2|RC_CACHED|RC_DRAWABLE) +#define RT_GC ((RESTYPE)3|RC_CACHED) +#undef RT_FONT +#undef RT_CURSOR +#define RT_FONT ((RESTYPE)4) +#define RT_CURSOR ((RESTYPE)5) +#define RT_COLORMAP ((RESTYPE)6) +#define RT_CMAPENTRY ((RESTYPE)7) +#define RT_OTHERCLIENT ((RESTYPE)8|RC_NEVERRETAIN) +#define RT_PASSIVEGRAB ((RESTYPE)9|RC_NEVERRETAIN) +#define RT_LASTPREDEF ((RESTYPE)9) +#define RT_NONE ((RESTYPE)0) + +/* bits and fields within a resource id */ +#define RESOURCE_AND_CLIENT_COUNT 29 /* 29 bits for XIDs */ +#if MAXCLIENTS == 64 +#define RESOURCE_CLIENT_BITS 6 +#endif +#if MAXCLIENTS == 128 +#define RESOURCE_CLIENT_BITS 7 +#endif +#if MAXCLIENTS == 256 +#define RESOURCE_CLIENT_BITS 8 +#endif +#if MAXCLIENTS == 512 +#define RESOURCE_CLIENT_BITS 9 +#endif +/* client field offset */ +#define CLIENTOFFSET (RESOURCE_AND_CLIENT_COUNT - RESOURCE_CLIENT_BITS) +/* resource field */ +#define RESOURCE_ID_MASK ((1 << CLIENTOFFSET) - 1) +/* client field */ +#define RESOURCE_CLIENT_MASK (((1 << RESOURCE_CLIENT_BITS) - 1) << CLIENTOFFSET) +/* extract the client mask from an XID */ +#define CLIENT_BITS(id) ((id) & RESOURCE_CLIENT_MASK) +/* extract the client id from an XID */ +#define CLIENT_ID(id) ((int)(CLIENT_BITS(id) >> CLIENTOFFSET)) +#define SERVER_BIT (Mask)0x40000000 /* use illegal bit */ + +#ifdef INVALID +#undef INVALID /* needed on HP/UX */ +#endif + +/* Invalid resource id */ +#define INVALID (0) + +#define BAD_RESOURCE 0xe0000000 + +typedef int (*DeleteType)( + pointer /*value*/, + XID /*id*/); + +typedef void (*FindResType)( + pointer /*value*/, + XID /*id*/, + pointer /*cdata*/); + +typedef void (*FindAllRes)( + pointer /*value*/, + XID /*id*/, + RESTYPE /*type*/, + pointer /*cdata*/); + +typedef Bool (*FindComplexResType)( + pointer /*value*/, + XID /*id*/, + pointer /*cdata*/); + +RESTYPE CreateNewResourceType( + DeleteType /*deleteFunc*/); + +Bool InitClientResources( + ClientPtr /*client*/); + +XID FakeClientID( + int /*client*/); + +/* Quartz support on Mac OS X uses the CarbonCore + framework whose AddResource function conflicts here. */ +Bool AddResource( + XID /*id*/, + RESTYPE /*type*/, + pointer /*value*/); + +void FreeResource( + XID /*id*/, + RESTYPE /*skipDeleteFuncType*/); + +void FreeResourceByType( + XID /*id*/, + RESTYPE /*type*/, + Bool /*skipFree*/); + +Bool ChangeResourceValue( + XID /*id*/, + RESTYPE /*rtype*/, + pointer /*value*/); + +void FindClientResourcesByType( + ClientPtr /*client*/, + RESTYPE /*type*/, + FindResType /*func*/, + pointer /*cdata*/); + +void FindAllClientResources( + ClientPtr /*client*/, + FindAllRes /*func*/, + pointer /*cdata*/); + +void FreeClientNeverRetainResources( + ClientPtr /*client*/); + +void FreeClientResources( + ClientPtr /*client*/); + +void FreeAllResources(void); + +Bool LegalNewID( + XID /*id*/, + ClientPtr /*client*/); + +pointer LookupIDByType( + XID /*id*/, + RESTYPE /*rtype*/); + +pointer LookupIDByClass( + XID /*id*/, + RESTYPE /*classes*/); + +pointer LookupClientResourceComplex( + ClientPtr client, + RESTYPE type, + FindComplexResType func, + pointer cdata); + +/* These are the access modes that can be passed in the last parameter + * to SecurityLookupIDByType/Class. The Security extension doesn't + * currently make much use of these; they're mainly provided as an + * example of what you might need for discretionary access control. + * You can or these values together to indicate multiple modes + * simultaneously. + */ + +#define SecurityUnknownAccess 0 /* don't know intentions */ +#define SecurityReadAccess (1<<0) /* inspecting the object */ +#define SecurityWriteAccess (1<<1) /* changing the object */ +#define SecurityDestroyAccess (1<<2) /* destroying the object */ + +pointer SecurityLookupIDByType( + ClientPtr /*client*/, + XID /*id*/, + RESTYPE /*rtype*/, + Mask /*access_mode*/); + +pointer SecurityLookupIDByClass( + ClientPtr /*client*/, + XID /*id*/, + RESTYPE /*classes*/, + Mask /*access_mode*/); + + +void GetXIDRange( + int /*client*/, + Bool /*server*/, + XID * /*minp*/, + XID * /*maxp*/); + +unsigned int GetXIDList( + ClientPtr /*client*/, + unsigned int /*count*/, + XID * /*pids*/); + +extern RESTYPE lastResourceType; +extern RESTYPE TypeMask; + +#ifdef XResExtension +extern Atom *ResourceNames; +void RegisterResourceName(RESTYPE type, char* name); +#endif + +#endif /* RESOURCE_H */ + diff --git a/include/screenint.h b/include/screenint.h new file mode 100644 index 0000000..3fbeee3 --- /dev/null +++ b/include/screenint.h @@ -0,0 +1,106 @@ +/*********************************************************** + +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. + +******************************************************************/ + +#ifndef SCREENINT_H +#define SCREENINT_H + +#include "misc.h" + +typedef struct _PixmapFormat *PixmapFormatPtr; +typedef struct _Visual *VisualPtr; +typedef struct _Depth *DepthPtr; +typedef struct _Screen *ScreenPtr; + +void ResetScreenPrivates(void); + +int AllocateScreenPrivateIndex(void); + +void ResetWindowPrivates(void); + +int AllocateWindowPrivateIndex(void); + +Bool AllocateWindowPrivate( + ScreenPtr /* pScreen */, + int /* index */, + unsigned /* amount */); + +void ResetGCPrivates(void); + +int AllocateGCPrivateIndex(void); + +Bool AllocateGCPrivate( + ScreenPtr /* pScreen */, + int /* index */, + unsigned /* amount */); + +int AddScreen( + Bool (* /*pfnInit*/)( + int /*index*/, + ScreenPtr /*pScreen*/, + int /*argc*/, + char ** /*argv*/), + int /*argc*/, + char** /*argv*/); + + +void ResetPixmapPrivates(void); + +int AllocatePixmapPrivateIndex(void); + +Bool AllocatePixmapPrivate( + ScreenPtr /* pScreen */, + int /* index */, + unsigned /* amount */); + + +void ResetColormapPrivates(void); + + +typedef struct _ColormapRec *ColormapPtr; +typedef int (*InitCmapPrivFunc)(ColormapPtr, int); + +#endif /* SCREENINT_H */ diff --git a/include/scrnintstr.h b/include/scrnintstr.h new file mode 100644 index 0000000..3058b70 --- /dev/null +++ b/include/scrnintstr.h @@ -0,0 +1,532 @@ +/*********************************************************** + +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. + +******************************************************************/ + +#ifndef SCREENINTSTRUCT_H +#define SCREENINTSTRUCT_H + +#include "screenint.h" +#include "regionstr.h" +#include "colormap.h" +#include "cursor.h" +#include "validate.h" +#include +#include "dix.h" + +typedef struct _PixmapFormat { + unsigned char depth; + unsigned char bitsPerPixel; + unsigned char scanlinePad; + } PixmapFormatRec; + +typedef struct _Visual { + VisualID vid; + short class; + short bitsPerRGBValue; + short ColormapEntries; + short nplanes;/* = log2 (ColormapEntries). This does not + * imply that the screen has this many planes. + * it may have more or fewer */ + unsigned long redMask, greenMask, blueMask; + int offsetRed, offsetGreen, offsetBlue; + } VisualRec; + +typedef struct _Depth { + unsigned char depth; + short numVids; + VisualID *vids; /* block of visual ids for this depth */ + } DepthRec; + + +/* + * There is a typedef for each screen function pointer so that code that + * needs to declare a screen function pointer (e.g. in a screen private + * or as a local variable) can easily do so and retain full type checking. + */ + +typedef Bool (* CloseScreenProcPtr)( + int /*index*/, + ScreenPtr /*pScreen*/); + +typedef void (* QueryBestSizeProcPtr)( + int /*class*/, + unsigned short * /*pwidth*/, + unsigned short * /*pheight*/, + ScreenPtr /*pScreen*/); + +typedef Bool (* SaveScreenProcPtr)( + ScreenPtr /*pScreen*/, + int /*on*/); + +typedef void (* GetImageProcPtr)( + DrawablePtr /*pDrawable*/, + int /*sx*/, + int /*sy*/, + int /*w*/, + int /*h*/, + unsigned int /*format*/, + unsigned long /*planeMask*/, + char * /*pdstLine*/); + +typedef void (* GetSpansProcPtr)( + DrawablePtr /*pDrawable*/, + int /*wMax*/, + DDXPointPtr /*ppt*/, + int* /*pwidth*/, + int /*nspans*/, + char * /*pdstStart*/); + +typedef void (* PointerNonInterestBoxProcPtr)( + ScreenPtr /*pScreen*/, + BoxPtr /*pBox*/); + +typedef void (* SourceValidateProcPtr)( + DrawablePtr /*pDrawable*/, + int /*x*/, + int /*y*/, + int /*width*/, + int /*height*/); + +typedef Bool (* CreateWindowProcPtr)( + WindowPtr /*pWindow*/); + +typedef Bool (* DestroyWindowProcPtr)( + WindowPtr /*pWindow*/); + +typedef Bool (* PositionWindowProcPtr)( + WindowPtr /*pWindow*/, + int /*x*/, + int /*y*/); + +typedef Bool (* ChangeWindowAttributesProcPtr)( + WindowPtr /*pWindow*/, + unsigned long /*mask*/); + +typedef Bool (* RealizeWindowProcPtr)( + WindowPtr /*pWindow*/); + +typedef Bool (* UnrealizeWindowProcPtr)( + WindowPtr /*pWindow*/); + +typedef void (* RestackWindowProcPtr)( + WindowPtr /*pWindow*/, + WindowPtr /*pOldNextSib*/); + +typedef int (* ValidateTreeProcPtr)( + WindowPtr /*pParent*/, + WindowPtr /*pChild*/, + VTKind /*kind*/); + +typedef void (* PostValidateTreeProcPtr)( + WindowPtr /*pParent*/, + WindowPtr /*pChild*/, + VTKind /*kind*/); + +typedef void (* WindowExposuresProcPtr)( + WindowPtr /*pWindow*/, + RegionPtr /*prgn*/, + RegionPtr /*other_exposed*/); + +typedef void (* PaintWindowProcPtr)( + WindowPtr /*pWindow*/, + RegionPtr /*pRegion*/, + int /*what*/); + +typedef PaintWindowProcPtr PaintWindowBackgroundProcPtr; +typedef PaintWindowProcPtr PaintWindowBorderProcPtr; + +typedef void (* CopyWindowProcPtr)( + WindowPtr /*pWindow*/, + DDXPointRec /*ptOldOrg*/, + RegionPtr /*prgnSrc*/); + +typedef void (* ClearToBackgroundProcPtr)( + WindowPtr /*pWindow*/, + int /*x*/, + int /*y*/, + int /*w*/, + int /*h*/, + Bool /*generateExposures*/); + +typedef void (* ClipNotifyProcPtr)( + WindowPtr /*pWindow*/, + int /*dx*/, + int /*dy*/); + +typedef PixmapPtr (* CreatePixmapProcPtr)( + ScreenPtr /*pScreen*/, + int /*width*/, + int /*height*/, + int /*depth*/); + +typedef Bool (* DestroyPixmapProcPtr)( + PixmapPtr /*pPixmap*/); + +typedef Bool (* RealizeFontProcPtr)( + ScreenPtr /*pScreen*/, + FontPtr /*pFont*/); + +typedef Bool (* UnrealizeFontProcPtr)( + ScreenPtr /*pScreen*/, + FontPtr /*pFont*/); + +typedef void (* ConstrainCursorProcPtr)( + ScreenPtr /*pScreen*/, + BoxPtr /*pBox*/); + +typedef void (* CursorLimitsProcPtr)( + ScreenPtr /*pScreen*/, + CursorPtr /*pCursor*/, + BoxPtr /*pHotBox*/, + BoxPtr /*pTopLeftBox*/); + +typedef Bool (* DisplayCursorProcPtr)( + ScreenPtr /*pScreen*/, + CursorPtr /*pCursor*/); + +typedef Bool (* RealizeCursorProcPtr)( + ScreenPtr /*pScreen*/, + CursorPtr /*pCursor*/); + +typedef Bool (* UnrealizeCursorProcPtr)( + ScreenPtr /*pScreen*/, + CursorPtr /*pCursor*/); + +typedef void (* RecolorCursorProcPtr)( + ScreenPtr /*pScreen*/, + CursorPtr /*pCursor*/, + Bool /*displayed*/); + +typedef Bool (* SetCursorPositionProcPtr)( + ScreenPtr /*pScreen*/, + int /*x*/, + int /*y*/, + Bool /*generateEvent*/); + +typedef Bool (* CreateGCProcPtr)( + GCPtr /*pGC*/); + +typedef Bool (* CreateColormapProcPtr)( + ColormapPtr /*pColormap*/); + +typedef void (* DestroyColormapProcPtr)( + ColormapPtr /*pColormap*/); + +typedef void (* InstallColormapProcPtr)( + ColormapPtr /*pColormap*/); + +typedef void (* UninstallColormapProcPtr)( + ColormapPtr /*pColormap*/); + +typedef int (* ListInstalledColormapsProcPtr) ( + ScreenPtr /*pScreen*/, + XID* /*pmaps */); + +typedef void (* StoreColorsProcPtr)( + ColormapPtr /*pColormap*/, + int /*ndef*/, + xColorItem * /*pdef*/); + +typedef void (* ResolveColorProcPtr)( + unsigned short* /*pred*/, + unsigned short* /*pgreen*/, + unsigned short* /*pblue*/, + VisualPtr /*pVisual*/); + +typedef RegionPtr (* BitmapToRegionProcPtr)( + PixmapPtr /*pPix*/); + +typedef void (* SendGraphicsExposeProcPtr)( + ClientPtr /*client*/, + RegionPtr /*pRgn*/, + XID /*drawable*/, + int /*major*/, + int /*minor*/); + +typedef void (* ScreenBlockHandlerProcPtr)( + int /*screenNum*/, + pointer /*blockData*/, + pointer /*pTimeout*/, + pointer /*pReadmask*/); + +typedef void (* ScreenWakeupHandlerProcPtr)( + int /*screenNum*/, + pointer /*wakeupData*/, + unsigned long /*result*/, + pointer /*pReadMask*/); + +typedef Bool (* CreateScreenResourcesProcPtr)( + ScreenPtr /*pScreen*/); + +typedef Bool (* ModifyPixmapHeaderProcPtr)( + PixmapPtr /*pPixmap*/, + int /*width*/, + int /*height*/, + int /*depth*/, + int /*bitsPerPixel*/, + int /*devKind*/, + pointer /*pPixData*/); + +typedef PixmapPtr (* GetWindowPixmapProcPtr)( + WindowPtr /*pWin*/); + +typedef void (* SetWindowPixmapProcPtr)( + WindowPtr /*pWin*/, + PixmapPtr /*pPix*/); + +typedef PixmapPtr (* GetScreenPixmapProcPtr)( + ScreenPtr /*pScreen*/); + +typedef void (* SetScreenPixmapProcPtr)( + PixmapPtr /*pPix*/); + +typedef void (* MarkWindowProcPtr)( + WindowPtr /*pWin*/); + +typedef Bool (* MarkOverlappedWindowsProcPtr)( + WindowPtr /*parent*/, + WindowPtr /*firstChild*/, + WindowPtr * /*pLayerWin*/); + +typedef void (* MoveWindowProcPtr)( + WindowPtr /*pWin*/, + int /*x*/, + int /*y*/, + WindowPtr /*pSib*/, + VTKind /*kind*/); + +typedef void (* ResizeWindowProcPtr)( + WindowPtr /*pWin*/, + int /*x*/, + int /*y*/, + unsigned int /*w*/, + unsigned int /*h*/, + WindowPtr /*pSib*/ +); + +typedef WindowPtr (* GetLayerWindowProcPtr)( + WindowPtr /*pWin*/ +); + +typedef void (* HandleExposuresProcPtr)( + WindowPtr /*pWin*/); + +typedef void (* ReparentWindowProcPtr)( + WindowPtr /*pWin*/, + WindowPtr /*pPriorParent*/); + +typedef void (* SetShapeProcPtr)( + WindowPtr /*pWin*/); + +typedef void (* ChangeBorderWidthProcPtr)( + WindowPtr /*pWin*/, + unsigned int /*width*/); + +typedef void (* MarkUnrealizedWindowProcPtr)( + WindowPtr /*pChild*/, + WindowPtr /*pWin*/, + Bool /*fromConfigure*/); + +typedef struct _Screen { + int myNum; /* index of this instance in Screens[] */ + ATOM id; + short width, height; + short mmWidth, mmHeight; + short numDepths; + unsigned char rootDepth; + DepthPtr allowedDepths; + unsigned long rootVisual; + unsigned long defColormap; + short minInstalledCmaps, maxInstalledCmaps; + char backingStoreSupport, saveUnderSupport; + unsigned long whitePixel, blackPixel; + unsigned long rgf; /* array of flags; she's -- HUNGARIAN */ + GCPtr GCperDepth[MAXFORMATS+1]; + /* next field is a stipple to use as default in + a GC. we don't build default tiles of all depths + because they are likely to be of a color + different from the default fg pixel, so + we don't win anything by building + a standard one. + */ + PixmapPtr PixmapPerDepth[1]; + pointer devPrivate; + short numVisuals; + VisualPtr visuals; + int WindowPrivateLen; + unsigned *WindowPrivateSizes; + unsigned totalWindowSize; + int GCPrivateLen; + unsigned *GCPrivateSizes; + unsigned totalGCSize; + + /* Random screen procedures */ + + CloseScreenProcPtr CloseScreen; + QueryBestSizeProcPtr QueryBestSize; + SaveScreenProcPtr SaveScreen; + GetImageProcPtr GetImage; + GetSpansProcPtr GetSpans; + PointerNonInterestBoxProcPtr PointerNonInterestBox; + SourceValidateProcPtr SourceValidate; + + /* Window Procedures */ + + CreateWindowProcPtr CreateWindow; + DestroyWindowProcPtr DestroyWindow; + PositionWindowProcPtr PositionWindow; + ChangeWindowAttributesProcPtr ChangeWindowAttributes; + RealizeWindowProcPtr RealizeWindow; + UnrealizeWindowProcPtr UnrealizeWindow; + ValidateTreeProcPtr ValidateTree; + PostValidateTreeProcPtr PostValidateTree; + WindowExposuresProcPtr WindowExposures; + PaintWindowBackgroundProcPtr PaintWindowBackground; + PaintWindowBorderProcPtr PaintWindowBorder; + CopyWindowProcPtr CopyWindow; + ClearToBackgroundProcPtr ClearToBackground; + ClipNotifyProcPtr ClipNotify; + RestackWindowProcPtr RestackWindow; + + /* Pixmap procedures */ + + CreatePixmapProcPtr CreatePixmap; + DestroyPixmapProcPtr DestroyPixmap; + + /* Font procedures */ + + RealizeFontProcPtr RealizeFont; + UnrealizeFontProcPtr UnrealizeFont; + + /* Cursor Procedures */ + + ConstrainCursorProcPtr ConstrainCursor; + CursorLimitsProcPtr CursorLimits; + DisplayCursorProcPtr DisplayCursor; + RealizeCursorProcPtr RealizeCursor; + UnrealizeCursorProcPtr UnrealizeCursor; + RecolorCursorProcPtr RecolorCursor; + SetCursorPositionProcPtr SetCursorPosition; + + /* GC procedures */ + + CreateGCProcPtr CreateGC; + + /* Colormap procedures */ + + CreateColormapProcPtr CreateColormap; + DestroyColormapProcPtr DestroyColormap; + InstallColormapProcPtr InstallColormap; + UninstallColormapProcPtr UninstallColormap; + ListInstalledColormapsProcPtr ListInstalledColormaps; + StoreColorsProcPtr StoreColors; + ResolveColorProcPtr ResolveColor; + + /* Region procedures */ + + BitmapToRegionProcPtr BitmapToRegion; + SendGraphicsExposeProcPtr SendGraphicsExpose; + + /* os layer procedures */ + + ScreenBlockHandlerProcPtr BlockHandler; + ScreenWakeupHandlerProcPtr WakeupHandler; + + pointer blockData; + pointer wakeupData; + + /* anybody can get a piece of this array */ + DevUnion *devPrivates; + + CreateScreenResourcesProcPtr CreateScreenResources; + ModifyPixmapHeaderProcPtr ModifyPixmapHeader; + + GetWindowPixmapProcPtr GetWindowPixmap; + SetWindowPixmapProcPtr SetWindowPixmap; + GetScreenPixmapProcPtr GetScreenPixmap; + SetScreenPixmapProcPtr SetScreenPixmap; + + PixmapPtr pScratchPixmap; /* scratch pixmap "pool" */ + + int PixmapPrivateLen; + unsigned int *PixmapPrivateSizes; + unsigned int totalPixmapSize; + + MarkWindowProcPtr MarkWindow; + MarkOverlappedWindowsProcPtr MarkOverlappedWindows; + MoveWindowProcPtr MoveWindow; + ResizeWindowProcPtr ResizeWindow; + GetLayerWindowProcPtr GetLayerWindow; + HandleExposuresProcPtr HandleExposures; + ReparentWindowProcPtr ReparentWindow; + + SetShapeProcPtr SetShape; + + ChangeBorderWidthProcPtr ChangeBorderWidth; + MarkUnrealizedWindowProcPtr MarkUnrealizedWindow; + +} ScreenRec; + +typedef struct _ScreenInfo { + int imageByteOrder; + int bitmapScanlineUnit; + int bitmapScanlinePad; + int bitmapBitOrder; + int numPixmapFormats; + PixmapFormatRec + formats[MAXFORMATS]; + int numScreens; + ScreenPtr screens[MAXSCREENS]; +} ScreenInfo; + +extern ScreenInfo screenInfo; + +void InitOutput( + ScreenInfo * /*pScreenInfo*/, + int /*argc*/, + char ** /*argv*/); + +#endif /* SCREENINTSTRUCT_H */ diff --git a/include/selection.h b/include/selection.h new file mode 100644 index 0000000..b24dea5 --- /dev/null +++ b/include/selection.h @@ -0,0 +1,68 @@ + +#ifndef SELECTION_H +#define SELECTION_H 1 + +/*********************************************************** + +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. + +******************************************************************/ + +#include "dixstruct.h" +/* + * + * Selection data structures + */ + +typedef struct _Selection { + Atom selection; + TimeStamp lastTimeChanged; + Window window; + WindowPtr pWin; + ClientPtr client; +} Selection; + +#endif /* SELECTION_H */ + + diff --git a/include/servermd.h b/include/servermd.h new file mode 100644 index 0000000..7b373ca --- /dev/null +++ b/include/servermd.h @@ -0,0 +1,397 @@ +/*********************************************************** + +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. + +******************************************************************/ + +#ifndef SERVERMD_H +#define SERVERMD_H 1 + +/* + * Machine dependent values: + * GLYPHPADBYTES should be chosen with consideration for the space-time + * trade-off. Padding to 0 bytes means that there is no wasted space + * in the font bitmaps (both on disk and in memory), but that access of + * the bitmaps will cause odd-address memory references. Padding to + * 2 bytes would ensure even address memory references and would + * be suitable for a 68010-class machine, but at the expense of wasted + * space in the font bitmaps. Padding to 4 bytes would be good + * for real 32 bit machines, etc. Be sure that you tell the font + * compiler what kind of padding you want because its defines are + * kept separate from this. See server/include/font.h for how + * GLYPHPADBYTES is used. + * + * Along with this, you should choose an appropriate value for + * GETLEFTBITS_ALIGNMENT, which is used in ddx/mfb/maskbits.h. This + * constant choses what kind of memory references are guarenteed during + * font access; either 1, 2 or 4, for byte, word or longword access, + * respectively. For instance, if you have decided to to have + * GLYPHPADBYTES == 4, then it is pointless for you to have a + * GETLEFTBITS_ALIGNMENT > 1, because the padding of the fonts has already + * guarenteed you that your fonts are longword aligned. On the other + * hand, even if you have chosen GLYPHPADBYTES == 1 to save space, you may + * also decide that the computing involved in aligning the pointer is more + * costly than an odd-address access; you choose GETLEFTBITS_ALIGNMENT == 1. + * + * Next, choose the tuning parameters which are appropriate for your + * hardware; these modify the behaviour of the raw frame buffer code + * in ddx/mfb and ddx/cfb. Defining these incorrectly will not cause + * the server to run incorrectly, but defining these correctly will + * cause some noticeable speed improvements: + * + * AVOID_MEMORY_READ - (8-bit cfb only) + * When stippling pixels on the screen (polytext and pushpixels), + * don't read long words from the display and mask in the + * appropriate values. Rather, perform multiple byte/short/long + * writes as appropriate. This option uses many more instructions + * but runs much faster when the destination is much slower than + * the CPU and at least 1 level of write buffer is availible (2 + * is much better). Defined currently for SPARC and MIPS. + * + * FAST_CONSTANT_OFFSET_MODE - (cfb and mfb) + * This define is used on machines which have no auto-increment + * addressing mode, but do have an effectively free constant-offset + * addressing mode. Currently defined for MIPS and SPARC, even though + * I remember the cg6 as performing better without it (cg3 definitely + * performs better with it). + * + * LARGE_INSTRUCTION_CACHE - + * This define increases the number of times some loops are + * unrolled. On 68020 machines (with 256 bytes of i-cache), + * this define will slow execution down as instructions miss + * the cache frequently. On machines with real i-caches, this + * reduces loop overhead, causing a slight performance improvement. + * Currently defined for MIPS and SPARC + * + * FAST_UNALIGNED_READS - + * For machines with more memory bandwidth than CPU, this + * define uses unaligned reads for 8-bit BitBLT instead of doing + * aligned reads and combining the results with shifts and + * logical-ors. Currently defined for 68020 and vax. + * PLENTIFUL_REGISTERS - + * For machines with > 20 registers. Currently used for + * unrolling the text painting code a bit more. Currently + * defined for MIPS. + * SHARED_IDCACHE - + * For non-Harvard RISC machines, those which share the same + * CPU memory bus for instructions and data. This unrolls some + * solid fill loops which are otherwise best left rolled up. + * Currently defined for SPARC. + */ + + +#ifdef __arm32__ + +#define IMAGE_BYTE_ORDER LSBFirst + +# if defined(XF86MONOVGA) || defined(XF86VGA16) || defined(XF86MONO) +# define BITMAP_BIT_ORDER MSBFirst +# else +# define BITMAP_BIT_ORDER LSBFirst +# endif + +# if defined(XF86MONOVGA) || defined(XF86VGA16) +# define BITMAP_SCANLINE_UNIT 8 +# endif + +#define GLYPHPADBYTES 4 +#define GETLEFTBITS_ALIGNMENT 1 +#define LARGE_INSTRUCTION_CACHE +#define AVOID_MEMORY_READ + +#endif /* __arm32__ */ + +#if defined(__powerpc__) || defined(__ppc__) + +#define IMAGE_BYTE_ORDER MSBFirst +#define BITMAP_BIT_ORDER MSBFirst +#define GLYPHPADBYTES 4 +#define GETLEFTBITS_ALIGNMENT 1 + +/* XXX Should this be for Lynx only? */ + +#define LARGE_INSTRUCTION_CACHE +#define FAST_CONSTANT_OFFSET_MODE +#define PLENTIFUL_REGISTERS +#define AVOID_MEMORY_READ + +#define FAST_MEMCPY + +#endif /* PowerPC */ + +#if defined(__sh__) + +#if defined(__BIG_ENDIAN__) +# define IMAGE_BYTE_ORDER MSBFirst +# define BITMAP_BIT_ORDER MSBFirst +# define GLYPHPADBYTES 4 +# define GETLEFTBITS_ALIGNMENT 1 +#else +# define IMAGE_BYTE_ORDER LSBFirst +# define BITMAP_BIT_ORDER LSBFirst +# define GLYPHPADBYTES 4 +# define GETLEFTBITS_ALIGNMENT 1 +#endif + +#define AVOID_MEMORY_READ +#define FAST_CONSTANT_OFFSET_MODE +#define LARGE_INSTRUCTION_CACHE +#define PLENTIFUL_REGISTERS + +#endif /* SuperH */ + + +#if (defined(sun) && (defined(__sparc) || defined(sparc))) || \ + (defined(__uxp__) && (defined(sparc) || defined(mc68000))) || \ + defined(__sparc__) || defined(__mc68000__) + +#if defined(__sparc) || defined(__sparc__) +# if !defined(sparc) +# define sparc 1 +# endif +#endif + +#if defined(sun386) || defined(sun5) +# define IMAGE_BYTE_ORDER LSBFirst /* Values for the SUN only */ +# define BITMAP_BIT_ORDER LSBFirst +#else +# define IMAGE_BYTE_ORDER MSBFirst /* Values for the SUN only */ +# define BITMAP_BIT_ORDER MSBFirst +#endif + +#ifdef sparc +# define AVOID_MEMORY_READ +# define LARGE_INSTRUCTION_CACHE +# define FAST_CONSTANT_OFFSET_MODE +# define SHARED_IDCACHE +#endif + +#ifdef mc68020 +#define FAST_UNALIGNED_READS +#endif + +#define GLYPHPADBYTES 4 +#define GETLEFTBITS_ALIGNMENT 1 + +#endif /* sun */ + + + +#if defined(ibm032) || defined (ibm) + +#ifdef i386 +# define IMAGE_BYTE_ORDER LSBFirst /* Value for PS/2 only */ +#else +# define IMAGE_BYTE_ORDER MSBFirst /* Values for the RT only*/ +#endif +#define BITMAP_BIT_ORDER MSBFirst +#define GLYPHPADBYTES 1 +#define GETLEFTBITS_ALIGNMENT 4 +/* ibm pcc doesn't understand pragmas. */ + +#ifdef i386 +#define BITMAP_SCANLINE_UNIT 8 +#endif + +#endif /* ibm */ + +#if (defined(mips) || defined(__mips)) && !defined(sgi) + +#if defined(MIPSEL) || defined(__MIPSEL__) +# define IMAGE_BYTE_ORDER LSBFirst /* Values for the PMAX only */ +# define BITMAP_BIT_ORDER LSBFirst +# define GLYPHPADBYTES 4 +# define GETLEFTBITS_ALIGNMENT 1 +#else +# define IMAGE_BYTE_ORDER MSBFirst /* Values for the MIPS only */ +# define BITMAP_BIT_ORDER MSBFirst +# define GLYPHPADBYTES 4 +# define GETLEFTBITS_ALIGNMENT 1 +#endif + +#define AVOID_MEMORY_READ +#define FAST_CONSTANT_OFFSET_MODE +#define LARGE_INSTRUCTION_CACHE +#define PLENTIFUL_REGISTERS + +#endif /* mips */ + +#if defined(__amd64__) || defined(amd64) || defined(__amd64) +# define IMAGE_BYTE_ORDER LSBFirst + +# if defined(XF86MONOVGA) || defined(XF86VGA16) || defined(XF86MONO) +# define BITMAP_BIT_ORDER MSBFirst +# else +# define BITMAP_BIT_ORDER LSBFirst +# endif + +# if defined(XF86MONOVGA) || defined(XF86VGA16) +# define BITMAP_SCANLINE_UNIT 8 +# endif + +# define GLYPHPADBYTES 4 +# define GETLEFTBITS_ALIGNMENT 1 +# define LARGE_INSTRUCTION_CACHE +# define FAST_CONSTANT_OFFSET_MODE +/* ???? */ +# define FAST_UNALIGNED_READS +#endif /* AMD64 */ + + + +#if defined(__alpha__) || defined(__alpha) || \ + defined(__i386__) || defined(__i386) || \ + defined(__UNIXOS2__) || \ + defined(__OS2ELF__) || \ + defined(__QNX__) || \ + defined(__s390x__) || defined(__s390__) + +#ifndef IMAGE_BYTE_ORDER +#define IMAGE_BYTE_ORDER LSBFirst +#endif + +#ifndef BITMAP_BIT_ORDER +# if defined(XF86MONOVGA) || defined(XF86VGA16) || defined(XF86MONO) +# define BITMAP_BIT_ORDER MSBFirst +# else +# define BITMAP_BIT_ORDER LSBFirst +# endif +#endif + +#ifndef BITMAP_SCANLINE_UNIT +# if defined(XF86MONOVGA) || defined(XF86VGA16) +# define BITMAP_SCANLINE_UNIT 8 +# endif +#endif + +#ifndef GLYPHPADBYTES +#define GLYPHPADBYTES 4 +#endif + +#define GETLEFTBITS_ALIGNMENT 1 +#define AVOID_MEMORY_READ + +#endif /* BSD / i386 */ + +#if defined (linux) && defined (__mc68000__) + +#define IMAGE_BYTE_ORDER MSBFirst +#define BITMAP_BIT_ORDER MSBFirst +#define FAST_UNALIGNED_READS +#define GLYPHPADBYTES 4 +#define GETLEFTBITS_ALIGNMENT 1 + +#endif /* linux/m68k */ + + +/* linux on the Compaq Itsy */ +#if defined(linux) && defined(__arm__) +#define IMAGE_BYTE_ORDER LSBFirst +#define BITMAP_BIT_ORDER LSBFirst +#define GLYPHPADBYTES 4 +#define GETLEFTBITS_ALIGNMENT 1 +#endif + +/* size of buffer to use with GetImage, measured in bytes. There's obviously + * a trade-off between the amount of stack (or whatever ALLOCATE_LOCAL gives + * you) used and the number of times the ddx routine has to be called. + */ +#ifndef IMAGE_BUFSIZE +#define IMAGE_BUFSIZE (64*1024) +#endif + +/* pad scanline to a longword */ +#ifndef BITMAP_SCANLINE_UNIT +#define BITMAP_SCANLINE_UNIT 32 +#endif + +#ifndef BITMAP_SCANLINE_PAD +#define BITMAP_SCANLINE_PAD 32 +#define LOG2_BITMAP_PAD 5 +#define LOG2_BYTES_PER_SCANLINE_PAD 2 +#endif + +/* + * This returns the number of padding units, for depth d and width w. + * For bitmaps this can be calculated with the macros above. + * Other depths require either grovelling over the formats field of the + * screenInfo or hardwired constants. + */ + +typedef struct _PaddingInfo { + int padRoundUp; /* pixels per pad unit - 1 */ + int padPixelsLog2; /* log 2 (pixels per pad unit) */ + int padBytesLog2; /* log 2 (bytes per pad unit) */ + int notPower2; /* bitsPerPixel not a power of 2 */ + int bytesPerPixel; /* only set when notPower2 is TRUE */ + int bitsPerPixel; /* bits per pixel */ +} PaddingInfo; +extern PaddingInfo PixmapWidthPaddingInfo[]; + +/* The only portable way to get the bpp from the depth is to look it up */ +#define BitsPerPixel(d) (PixmapWidthPaddingInfo[d].bitsPerPixel) + +#define PixmapWidthInPadUnits(w, d) \ + (PixmapWidthPaddingInfo[d].notPower2 ? \ + (((int)(w) * PixmapWidthPaddingInfo[d].bytesPerPixel + \ + PixmapWidthPaddingInfo[d].bytesPerPixel) >> \ + PixmapWidthPaddingInfo[d].padBytesLog2) : \ + ((int)((w) + PixmapWidthPaddingInfo[d].padRoundUp) >> \ + PixmapWidthPaddingInfo[d].padPixelsLog2)) + +/* + * Return the number of bytes to which a scanline of the given + * depth and width will be padded. + */ +#define PixmapBytePad(w, d) \ + (PixmapWidthInPadUnits(w, d) << PixmapWidthPaddingInfo[d].padBytesLog2) + +#define BitmapBytePad(w) \ + (((int)((w) + BITMAP_SCANLINE_PAD - 1) >> LOG2_BITMAP_PAD) << LOG2_BYTES_PER_SCANLINE_PAD) + +#define PixmapWidthInPadUnitsProto(w, d) PixmapWidthInPadUnits(w, d) +#define PixmapBytePadProto(w, d) PixmapBytePad(w, d) +#define BitmapBytePadProto(w) BitmapBytePad(w) + +#endif /* SERVERMD_H */ diff --git a/include/site.h b/include/site.h new file mode 100644 index 0000000..bacc772 --- /dev/null +++ b/include/site.h @@ -0,0 +1,130 @@ +/************************************************************ + +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. + +********************************************************/ + +#ifndef SITE_H +#define SITE_H +/* + * The vendor string identifies the vendor responsible for the + * server executable. + */ +#ifndef VENDOR_STRING +#define VENDOR_STRING "The X.Org Group" +#endif + +/* + * The vendor release number identifies, for the purpose of submitting + * traceable bug reports, the release number of software produced + * by the vendor. + */ +#ifndef VENDOR_RELEASE +#define VENDOR_RELEASE 6600 +#endif + +/* + * The following constants are provided solely as a last line of defense. The + * normal build ALWAYS overrides them using a special rule given in + * server/dix/Imakefile. If you want to change either of these constants, + * you should set the DefaultFontPath or DefaultRGBDatabase configuration + * parameters. + * DO NOT CHANGE THESE VALUES OR THE DIX IMAKEFILE! + */ +#ifndef COMPILEDDEFAULTFONTPATH +#define COMPILEDDEFAULTFONTPATH "/usr/lib/X11/fonts/misc/" +#endif + +/* + * The following constants contain default values for all of the variables + * that can be initialized on the server command line or in the environment. + */ +#define COMPILEDDEFAULTFONT "fixed" +#define COMPILEDCURSORFONT "cursor" +#ifndef COMPILEDDISPLAYCLASS +#define COMPILEDDISPLAYCLASS "MIT-unspecified" +#endif +#define DEFAULT_TIMEOUT 60 /* seconds */ +#define DEFAULT_KEYBOARD_CLICK 0 +#define DEFAULT_BELL 50 +#define DEFAULT_BELL_PITCH 400 +#define DEFAULT_BELL_DURATION 100 +#define DEFAULT_AUTOREPEAT FALSE +#define DEFAULT_AUTOREPEATS {\ + 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\ + 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} + +#define DEFAULT_LEDS 0x0 /* all off */ +#define DEFAULT_LEDS_MASK 0xffffffff /* 32 */ +#define DEFAULT_INT_RESOLUTION 1000 +#define DEFAULT_INT_MIN_VALUE 0 +#define DEFAULT_INT_MAX_VALUE 100 +#define DEFAULT_INT_DISPLAYED 0 + +#define DEFAULT_PTR_NUMERATOR 2 +#define DEFAULT_PTR_DENOMINATOR 1 +#define DEFAULT_PTR_THRESHOLD 4 + +#define DEFAULT_SCREEN_SAVER_TIME (10 * (60 * 1000)) +#define DEFAULT_SCREEN_SAVER_INTERVAL (10 * (60 * 1000)) +#define DEFAULT_SCREEN_SAVER_BLANKING PreferBlanking +#define DEFAULT_SCREEN_SAVER_EXPOSURES AllowExposures +#ifndef NOLOGOHACK +#define DEFAULT_LOGO_SCREEN_SAVER 1 +#endif +#ifndef DEFAULT_ACCESS_CONTROL +#define DEFAULT_ACCESS_CONTROL TRUE +#endif + +/* Default logging parameters. */ +#ifndef DEFAULT_LOG_VERBOSITY +#define DEFAULT_LOG_VERBOSITY 0 +#endif +#ifndef DEFAULT_LOG_FILE_VERBOSITY +#define DEFAULT_LOG_FILE_VERBOSITY 3 +#endif + +#endif /* SITE_H */ diff --git a/include/swaprep.h b/include/swaprep.h new file mode 100644 index 0000000..bacd0f1 --- /dev/null +++ b/include/swaprep.h @@ -0,0 +1,310 @@ +/************************************************************ + +Copyright 1996 by Thomas E. Dickey + + 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. + +********************************************************/ + +#ifndef SWAPREP_H +#define SWAPREP_H 1 + +void Swap32Write( + ClientPtr /* pClient */, + int /* size */, + CARD32 * /* pbuf */); + +void CopySwap32Write( + ClientPtr /* pClient */, + int /* size */, + CARD32 * /* pbuf */); + +void CopySwap16Write( + ClientPtr /* pClient */, + int /* size */, + short * /* pbuf */); + +void SGenericReply( + ClientPtr /* pClient */, + int /* size */, + xGenericReply * /* pRep */); + +void SGetWindowAttributesReply( + ClientPtr /* pClient */, + int /* size */, + xGetWindowAttributesReply * /* pRep */); + +void SGetGeometryReply( + ClientPtr /* pClient */, + int /* size */, + xGetGeometryReply * /* pRep */); + +void SQueryTreeReply( + ClientPtr /* pClient */, + int /* size */, + xQueryTreeReply * /* pRep */); + +void SInternAtomReply( + ClientPtr /* pClient */, + int /* size */, + xInternAtomReply * /* pRep */); + +void SGetAtomNameReply( + ClientPtr /* pClient */, + int /* size */, + xGetAtomNameReply * /* pRep */); + +void SGetPropertyReply( + ClientPtr /* pClient */, + int /* size */, + xGetPropertyReply * /* pRep */); + +void SListPropertiesReply( + ClientPtr /* pClient */, + int /* size */, + xListPropertiesReply * /* pRep */); + +void SGetSelectionOwnerReply( + ClientPtr /* pClient */, + int /* size */, + xGetSelectionOwnerReply * /* pRep */); + +void SQueryPointerReply( + ClientPtr /* pClient */, + int /* size */, + xQueryPointerReply * /* pRep */); + +void SwapTimecoord( + xTimecoord * /* pCoord */); + +void SwapTimeCoordWrite( + ClientPtr /* pClient */, + int /* size */, + xTimecoord * /* pRep */); + +void SGetMotionEventsReply( + ClientPtr /* pClient */, + int /* size */, + xGetMotionEventsReply * /* pRep */); + +void STranslateCoordsReply( + ClientPtr /* pClient */, + int /* size */, + xTranslateCoordsReply * /* pRep */); + +void SGetInputFocusReply( + ClientPtr /* pClient */, + int /* size */, + xGetInputFocusReply * /* pRep */); + +void SQueryKeymapReply( + ClientPtr /* pClient */, + int /* size */, + xQueryKeymapReply * /* pRep */); + +void SQueryFontReply( + ClientPtr /* pClient */, + int /* size */, + xQueryFontReply * /* pRep */); + +void SQueryTextExtentsReply( + ClientPtr /* pClient */, + int /* size */, + xQueryTextExtentsReply * /* pRep */); + +void SListFontsReply( + ClientPtr /* pClient */, + int /* size */, + xListFontsReply * /* pRep */); + +void SListFontsWithInfoReply( + ClientPtr /* pClient */, + int /* size */, + xListFontsWithInfoReply * /* pRep */); + +void SGetFontPathReply( + ClientPtr /* pClient */, + int /* size */, + xGetFontPathReply * /* pRep */); + +void SGetImageReply( + ClientPtr /* pClient */, + int /* size */, + xGetImageReply * /* pRep */); + +void SListInstalledColormapsReply( + ClientPtr /* pClient */, + int /* size */, + xListInstalledColormapsReply * /* pRep */); + +void SAllocColorReply( + ClientPtr /* pClient */, + int /* size */, + xAllocColorReply * /* pRep */); + +void SAllocNamedColorReply( + ClientPtr /* pClient */, + int /* size */, + xAllocNamedColorReply * /* pRep */); + +void SAllocColorCellsReply( + ClientPtr /* pClient */, + int /* size */, + xAllocColorCellsReply * /* pRep */); + +void SAllocColorPlanesReply( + ClientPtr /* pClient */, + int /* size */, + xAllocColorPlanesReply * /* pRep */); + +void SwapRGB( + xrgb * /* prgb */); + +void SQColorsExtend( + ClientPtr /* pClient */, + int /* size */, + xrgb * /* prgb */); + +void SQueryColorsReply( + ClientPtr /* pClient */, + int /* size */, + xQueryColorsReply * /* pRep */); + +void SLookupColorReply( + ClientPtr /* pClient */, + int /* size */, + xLookupColorReply * /* pRep */); + +void SQueryBestSizeReply( + ClientPtr /* pClient */, + int /* size */, + xQueryBestSizeReply * /* pRep */); + +void SListExtensionsReply( + ClientPtr /* pClient */, + int /* size */, + xListExtensionsReply * /* pRep */); + +void SGetKeyboardMappingReply( + ClientPtr /* pClient */, + int /* size */, + xGetKeyboardMappingReply * /* pRep */); + +void SGetPointerMappingReply( + ClientPtr /* pClient */, + int /* size */, + xGetPointerMappingReply * /* pRep */); + +void SGetModifierMappingReply( + ClientPtr /* pClient */, + int /* size */, + xGetModifierMappingReply * /* pRep */); + +void SGetKeyboardControlReply( + ClientPtr /* pClient */, + int /* size */, + xGetKeyboardControlReply * /* pRep */); + +void SGetPointerControlReply( + ClientPtr /* pClient */, + int /* size */, + xGetPointerControlReply * /* pRep */); + +void SGetScreenSaverReply( + ClientPtr /* pClient */, + int /* size */, + xGetScreenSaverReply * /* pRep */); + +void SLHostsExtend( + ClientPtr /* pClient */, + int /* size */, + char * /* buf */); + +void SListHostsReply( + ClientPtr /* pClient */, + int /* size */, + xListHostsReply * /* pRep */); + +void SErrorEvent( + xError * /* from */, + xError * /* to */); + +void SwapConnSetupInfo( + char * /* pInfo */, + char * /* pInfoTBase */); + +void WriteSConnectionInfo( + ClientPtr /* pClient */, + unsigned long /* size */, + char * /* pInfo */); + +void SwapConnSetup( + xConnSetup * /* pConnSetup */, + xConnSetup * /* pConnSetupT */); + +void SwapWinRoot( + xWindowRoot * /* pRoot */, + xWindowRoot * /* pRootT */); + +void SwapVisual( + xVisualType * /* pVis */, + xVisualType * /* pVisT */); + +void SwapConnSetupPrefix( + xConnSetupPrefix * /* pcspFrom */, + xConnSetupPrefix * /* pcspTo */); + +void WriteSConnSetupPrefix( + ClientPtr /* pClient */, + xConnSetupPrefix * /* pcsp */); + +#undef SWAPREP_PROC +#define SWAPREP_PROC(func) void func(xEvent * /* from */, xEvent * /* to */) + +SWAPREP_PROC(SCirculateEvent); +SWAPREP_PROC(SClientMessageEvent); +SWAPREP_PROC(SColormapEvent); +SWAPREP_PROC(SConfigureNotifyEvent); +SWAPREP_PROC(SConfigureRequestEvent); +SWAPREP_PROC(SCreateNotifyEvent); +SWAPREP_PROC(SDestroyNotifyEvent); +SWAPREP_PROC(SEnterLeaveEvent); +SWAPREP_PROC(SExposeEvent); +SWAPREP_PROC(SFocusEvent); +SWAPREP_PROC(SGraphicsExposureEvent); +SWAPREP_PROC(SGravityEvent); +SWAPREP_PROC(SKeyButtonPtrEvent); +SWAPREP_PROC(SKeymapNotifyEvent); +SWAPREP_PROC(SMapNotifyEvent); +SWAPREP_PROC(SMapRequestEvent); +SWAPREP_PROC(SMappingEvent); +SWAPREP_PROC(SNoExposureEvent); +SWAPREP_PROC(SPropertyEvent); +SWAPREP_PROC(SReparentEvent); +SWAPREP_PROC(SResizeRequestEvent); +SWAPREP_PROC(SSelectionClearEvent); +SWAPREP_PROC(SSelectionNotifyEvent); +SWAPREP_PROC(SSelectionRequestEvent); +SWAPREP_PROC(SUnmapNotifyEvent); +SWAPREP_PROC(SVisibilityEvent); + +#undef SWAPREP_PROC + +#endif /* SWAPREP_H */ diff --git a/include/swapreq.h b/include/swapreq.h new file mode 100644 index 0000000..03d3447 --- /dev/null +++ b/include/swapreq.h @@ -0,0 +1,119 @@ +/************************************************************ + +Copyright 1996 by Thomas E. Dickey + + 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. + +********************************************************/ + +#ifndef SWAPREQ_H +#define SWAPREQ_H 1 + +/* The first two are in misc.h */ +#if 0 +void SwapLongs ( + CARD32 * /* list */, + unsigned long /* count */); + +void SwapShorts ( + short * /* list */, + unsigned long /* count */); +#endif + +void SwapColorItem( + xColorItem * /* pItem */); + +void SwapConnClientPrefix( + xConnClientPrefix * /* pCCP */); + +#undef SWAPREQ_PROC + +#define SWAPREQ_PROC(func) int func(ClientPtr /* client */) + +SWAPREQ_PROC(SProcAllocColor); +SWAPREQ_PROC(SProcAllocColorCells); +SWAPREQ_PROC(SProcAllocColorPlanes); +SWAPREQ_PROC(SProcAllocNamedColor); +SWAPREQ_PROC(SProcChangeActivePointerGrab); +SWAPREQ_PROC(SProcChangeGC); +SWAPREQ_PROC(SProcChangeHosts); +SWAPREQ_PROC(SProcChangeKeyboardControl); +SWAPREQ_PROC(SProcChangeKeyboardMapping); +SWAPREQ_PROC(SProcChangePointerControl); +SWAPREQ_PROC(SProcChangeProperty); +SWAPREQ_PROC(SProcChangeWindowAttributes); +SWAPREQ_PROC(SProcClearToBackground); +SWAPREQ_PROC(SProcConfigureWindow); +SWAPREQ_PROC(SProcConvertSelection); +SWAPREQ_PROC(SProcCopyArea); +SWAPREQ_PROC(SProcCopyColormapAndFree); +SWAPREQ_PROC(SProcCopyGC); +SWAPREQ_PROC(SProcCopyPlane); +SWAPREQ_PROC(SProcCreateColormap); +SWAPREQ_PROC(SProcCreateCursor); +SWAPREQ_PROC(SProcCreateGC); +SWAPREQ_PROC(SProcCreateGlyphCursor); +SWAPREQ_PROC(SProcCreatePixmap); +SWAPREQ_PROC(SProcCreateWindow); +SWAPREQ_PROC(SProcDeleteProperty); +SWAPREQ_PROC(SProcFillPoly); +SWAPREQ_PROC(SProcFreeColors); +SWAPREQ_PROC(SProcGetImage); +SWAPREQ_PROC(SProcGetMotionEvents); +SWAPREQ_PROC(SProcGetProperty); +SWAPREQ_PROC(SProcGrabButton); +SWAPREQ_PROC(SProcGrabKey); +SWAPREQ_PROC(SProcGrabKeyboard); +SWAPREQ_PROC(SProcGrabPointer); +SWAPREQ_PROC(SProcImageText); +SWAPREQ_PROC(SProcInternAtom); +SWAPREQ_PROC(SProcListFonts); +SWAPREQ_PROC(SProcListFontsWithInfo); +SWAPREQ_PROC(SProcLookupColor); +SWAPREQ_PROC(SProcNoOperation); +SWAPREQ_PROC(SProcOpenFont); +SWAPREQ_PROC(SProcPoly); +SWAPREQ_PROC(SProcPolyText); +SWAPREQ_PROC(SProcPutImage); +SWAPREQ_PROC(SProcQueryBestSize); +SWAPREQ_PROC(SProcQueryColors); +SWAPREQ_PROC(SProcQueryExtension); +SWAPREQ_PROC(SProcRecolorCursor); +SWAPREQ_PROC(SProcReparentWindow); +SWAPREQ_PROC(SProcResourceReq); +SWAPREQ_PROC(SProcRotateProperties); +SWAPREQ_PROC(SProcSendEvent); +SWAPREQ_PROC(SProcSetClipRectangles); +SWAPREQ_PROC(SProcSetDashes); +SWAPREQ_PROC(SProcSetFontPath); +SWAPREQ_PROC(SProcSetInputFocus); +SWAPREQ_PROC(SProcSetScreenSaver); +SWAPREQ_PROC(SProcSetSelectionOwner); +SWAPREQ_PROC(SProcSimpleReq); +SWAPREQ_PROC(SProcStoreColors); +SWAPREQ_PROC(SProcStoreNamedColor); +SWAPREQ_PROC(SProcTranslateCoords); +SWAPREQ_PROC(SProcUngrabButton); +SWAPREQ_PROC(SProcUngrabKey); +SWAPREQ_PROC(SProcWarpPointer); + +#undef SWAPREQ_PROC + +#endif /* SWAPREQ_H */ diff --git a/include/validate.h b/include/validate.h new file mode 100644 index 0000000..e88fb41 --- /dev/null +++ b/include/validate.h @@ -0,0 +1,40 @@ + +/* + +Copyright 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. +*/ + +#ifndef VALIDATE_H +#define VALIDATE_H + +#include "miscstruct.h" +#include "regionstr.h" + +typedef enum { VTOther, VTStack, VTMove, VTUnmap, VTMap, VTBroken } VTKind; + +/* union _Validate is now device dependent; see mivalidate.h for an example */ +typedef union _Validate *ValidatePtr; + +#define UnmapValData ((ValidatePtr)1) + +#endif /* VALIDATE_H */ diff --git a/include/window.h b/include/window.h new file mode 100644 index 0000000..7e1e3be --- /dev/null +++ b/include/window.h @@ -0,0 +1,264 @@ +/*********************************************************** + +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. + +******************************************************************/ + +#ifndef WINDOW_H +#define WINDOW_H + +#include "misc.h" +#include "region.h" +#include "screenint.h" +#include + +#define TOTALLY_OBSCURED 0 +#define UNOBSCURED 1 +#define OBSCURED 2 + +#define VisibilityNotViewable 3 + +/* return values for tree-walking callback procedures */ +#define WT_STOPWALKING 0 +#define WT_WALKCHILDREN 1 +#define WT_DONTWALKCHILDREN 2 +#define WT_NOMATCH 3 +#define NullWindow ((WindowPtr) 0) + +typedef struct _Window *WindowPtr; + +typedef int (*VisitWindowProcPtr)( + WindowPtr /*pWin*/, + pointer /*data*/); + +int TraverseTree( + WindowPtr /*pWin*/, + VisitWindowProcPtr /*func*/, + pointer /*data*/); + +int WalkTree( + ScreenPtr /*pScreen*/, + VisitWindowProcPtr /*func*/, + pointer /*data*/); + +WindowPtr AllocateWindow( + ScreenPtr /*pScreen*/); + +Bool CreateRootWindow( + ScreenPtr /*pScreen*/); + +void InitRootWindow( + WindowPtr /*pWin*/); + +void ClippedRegionFromBox( + WindowPtr /*pWin*/, + RegionPtr /*Rgn*/, + int /*x*/, + int /*y*/, + int /*w*/, + int /*h*/); + +typedef WindowPtr (* RealChildHeadProc) (WindowPtr pWin); + +void RegisterRealChildHeadProc (RealChildHeadProc proc); + +WindowPtr RealChildHead( + WindowPtr /*pWin*/); + +WindowPtr CreateWindow( + Window /*wid*/, + WindowPtr /*pParent*/, + int /*x*/, + int /*y*/, + unsigned int /*w*/, + unsigned int /*h*/, + unsigned int /*bw*/, + unsigned int /*class*/, + Mask /*vmask*/, + XID* /*vlist*/, + int /*depth*/, + ClientPtr /*client*/, + VisualID /*visual*/, + int* /*error*/); + +int DeleteWindow( + pointer /*pWin*/, + XID /*wid*/); + +void DestroySubwindows( + WindowPtr /*pWin*/, + ClientPtr /*client*/); + +/* Quartz support on Mac OS X uses the HIToolbox + framework whose ChangeWindowAttributes function conflicts here. */ +int ChangeWindowAttributes( + WindowPtr /*pWin*/, + Mask /*vmask*/, + XID* /*vlist*/, + ClientPtr /*client*/); + +/* Quartz support on Mac OS X uses the HIToolbox + framework whose GetWindowAttributes function conflicts here. */ +void GetWindowAttributes( + WindowPtr /*pWin*/, + ClientPtr /*client*/, + xGetWindowAttributesReply* /* wa */); + +void GravityTranslate( + int /*x*/, + int /*y*/, + int /*oldx*/, + int /*oldy*/, + int /*dw*/, + int /*dh*/, + unsigned /*gravity*/, + int* /*destx*/, + int* /*desty*/); + +int ConfigureWindow( + WindowPtr /*pWin*/, + Mask /*mask*/, + XID* /*vlist*/, + ClientPtr /*client*/); + +int CirculateWindow( + WindowPtr /*pParent*/, + int /*direction*/, + ClientPtr /*client*/); + +int ReparentWindow( + WindowPtr /*pWin*/, + WindowPtr /*pParent*/, + int /*x*/, + int /*y*/, + ClientPtr /*client*/); + +int MapWindow( + WindowPtr /*pWin*/, + ClientPtr /*client*/); + +void MapSubwindows( + WindowPtr /*pParent*/, + ClientPtr /*client*/); + +int UnmapWindow( + WindowPtr /*pWin*/, + Bool /*fromConfigure*/); + +void UnmapSubwindows( + WindowPtr /*pWin*/); + +void HandleSaveSet( + ClientPtr /*client*/); + +Bool VisibleBoundingBoxFromPoint( + WindowPtr /*pWin*/, + int /*x*/, + int /*y*/, + BoxPtr /*box*/); + +Bool PointInWindowIsVisible( + WindowPtr /*pWin*/, + int /*x*/, + int /*y*/); + +RegionPtr NotClippedByChildren( + WindowPtr /*pWin*/); + +void SendVisibilityNotify( + WindowPtr /*pWin*/); + +void SaveScreens( + int /*on*/, + int /*mode*/); + +WindowPtr FindWindowWithOptional( + WindowPtr /*w*/); + +void CheckWindowOptionalNeed( + WindowPtr /*w*/); + +Bool MakeWindowOptional( + WindowPtr /*pWin*/); + +void DisposeWindowOptional( + WindowPtr /*pWin*/); + +WindowPtr MoveWindowInStack( + WindowPtr /*pWin*/, + WindowPtr /*pNextSib*/); + +void SetWinSize( + WindowPtr /*pWin*/); + +void SetBorderSize( + WindowPtr /*pWin*/); + +void ResizeChildrenWinSize( + WindowPtr /*pWin*/, + int /*dx*/, + int /*dy*/, + int /*dw*/, + int /*dh*/); + +void ShapeExtensionInit(void); + +void SendShapeNotify( + WindowPtr /* pWin */, + int /* which */ ); + +RegionPtr CreateBoundingShape( + WindowPtr /* pWin */ ); + +RegionPtr CreateClipShape( + WindowPtr /* pWin */ ); + +void DisableMapUnmapEvents( + WindowPtr /* pWin */ ); +void EnableMapUnmapEvents( + WindowPtr /* pWin */ ); +Bool MapUnmapEventsEnabled( + WindowPtr /* pWin */ ); + +#endif /* WINDOW_H */ diff --git a/include/windowstr.h b/include/windowstr.h new file mode 100644 index 0000000..9910506 --- /dev/null +++ b/include/windowstr.h @@ -0,0 +1,191 @@ +/*********************************************************** + +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. + +******************************************************************/ + +#ifndef WINDOWSTRUCT_H +#define WINDOWSTRUCT_H + +#include "window.h" +#include "pixmapstr.h" +#include "regionstr.h" +#include "cursor.h" +#include "property.h" +#include "resource.h" /* for ROOT_WINDOW_ID_BASE */ +#include "dix.h" +#include "miscstruct.h" +#include +#include "opaque.h" + +#define GuaranteeNothing 0 +#define GuaranteeVisBack 1 + +#define SameBackground(as, a, bs, b) \ + ((as) == (bs) && ((as) == None || \ + (as) == ParentRelative || \ + SamePixUnion(a,b,as == BackgroundPixel))) + +#define SameBorder(as, a, bs, b) \ + EqualPixUnion(as, a, bs, b) + +typedef struct _WindowOpt { + VisualID visual; /* default: same as parent */ + CursorPtr cursor; /* default: window.cursorNone */ + Colormap colormap; /* default: same as parent */ + Mask dontPropagateMask; /* default: window.dontPropagate */ + Mask otherEventMasks; /* default: 0 */ + struct _OtherClients *otherClients; /* default: NULL */ + struct _GrabRec *passiveGrabs; /* default: NULL */ + PropertyPtr userProps; /* default: NULL */ + unsigned long backingBitPlanes; /* default: ~0L */ + unsigned long backingPixel; /* default: 0 */ + RegionPtr boundingShape; /* default: NULL */ + RegionPtr clipShape; /* default: NULL */ + RegionPtr inputShape; /* default: NULL */ +} WindowOptRec, *WindowOptPtr; + +#define BackgroundPixel 2L +#define BackgroundPixmap 3L + +typedef struct _Window { + DrawableRec drawable; + WindowPtr parent; /* ancestor chain */ + WindowPtr nextSib; /* next lower sibling */ + WindowPtr prevSib; /* next higher sibling */ + WindowPtr firstChild; /* top-most child */ + WindowPtr lastChild; /* bottom-most child */ + RegionRec clipList; /* clipping rectangle for output */ + RegionRec borderClip; /* NotClippedByChildren + border */ + union _Validate *valdata; + RegionRec winSize; + RegionRec borderSize; + DDXPointRec origin; /* position relative to parent */ + unsigned short borderWidth; + unsigned short deliverableEvents; + Mask eventMask; + PixUnion background; + PixUnion border; + pointer backStorage; /* null when BS disabled */ + WindowOptPtr optional; + unsigned backgroundState:2; /* None, Relative, Pixel, Pixmap */ + unsigned borderIsPixel:1; + unsigned cursorIsNone:1; /* else real cursor (might inherit) */ + unsigned backingStore:2; + unsigned saveUnder:1; + unsigned DIXsaveUnder:1; + unsigned bitGravity:4; + unsigned winGravity:4; + unsigned overrideRedirect:1; + unsigned visibility:2; + unsigned mapped:1; + unsigned realized:1; /* ancestors are all mapped */ + unsigned viewable:1; /* realized && InputOutput */ + unsigned dontPropagate:3;/* index into DontPropagateMasks */ + unsigned forcedBS:1; /* system-supplied backingStore */ +#ifdef NEED_DBE_BUF_BITS +#define DBE_FRONT_BUFFER 1 +#define DBE_BACK_BUFFER 0 + unsigned dstBuffer:1; /* destination buffer for rendering */ + unsigned srcBuffer:1; /* source buffer for rendering */ +#endif + DevUnion *devPrivates; +} WindowRec; + +/* + * Ok, a bunch of macros for accessing the optional record + * fields (or filling the appropriate default value) + */ + +extern Mask DontPropagateMasks[]; + +#define wTrackParent(w,field) ((w)->optional ? \ + (w)->optional->field \ + : FindWindowWithOptional(w)->optional->field) +#define wUseDefault(w,field,def) ((w)->optional ? \ + (w)->optional->field \ + : def) + +#define wVisual(w) wTrackParent(w, visual) +#define wCursor(w) ((w)->cursorIsNone ? None : wTrackParent(w, cursor)) +#define wColormap(w) ((w)->drawable.class == InputOnly ? None : wTrackParent(w, colormap)) +#define wDontPropagateMask(w) wUseDefault(w, dontPropagateMask, DontPropagateMasks[(w)->dontPropagate]) +#define wOtherEventMasks(w) wUseDefault(w, otherEventMasks, 0) +#define wOtherClients(w) wUseDefault(w, otherClients, NULL) +#define wOtherInputMasks(w) NULL +#define wPassiveGrabs(w) wUseDefault(w, passiveGrabs, NULL) +#define wUserProps(w) wUseDefault(w, userProps, NULL) +#define wBackingBitPlanes(w) wUseDefault(w, backingBitPlanes, ~0L) +#define wBackingPixel(w) wUseDefault(w, backingPixel, 0) +#define wBoundingShape(w) wUseDefault(w, boundingShape, NULL) +#define wClipShape(w) wUseDefault(w, clipShape, NULL) +#define wInputShape(w) wUseDefault(w, inputShape, NULL) +#define wClient(w) (clients[CLIENT_ID((w)->drawable.id)]) +#define wBorderWidth(w) ((int) (w)->borderWidth) + +/* true when w needs a border drawn. */ + +#define HasBorder(w) ((w)->borderWidth || wClipShape(w)) + +typedef struct _ScreenSaverStuff { + WindowPtr pWindow; + XID wid; + char blanked; + Bool (*ExternalScreenSaver)( + ScreenPtr /*pScreen*/, + int /*xstate*/, + Bool /*force*/); +} ScreenSaverStuffRec, *ScreenSaverStuffPtr; + +#define SCREEN_IS_BLANKED 0 +#define SCREEN_ISNT_SAVED 1 +#define SCREEN_IS_TILED 2 +#define SCREEN_IS_BLACK 3 + +#define HasSaverWindow(i) (savedScreenInfo[i].pWindow != NullWindow) + +extern int screenIsSaved; +extern ScreenSaverStuffRec savedScreenInfo[MAXSCREENS]; + +#endif /* WINDOWSTRUCT_H */ diff --git a/kdrive/Makefile.am b/kdrive/Makefile.am new file mode 100644 index 0000000..8f0bd76 --- /dev/null +++ b/kdrive/Makefile.am @@ -0,0 +1,19 @@ +if KDRIVEVESA +VESA_SUBDIRS = vesa +endif + +if KDRIVEFBDEV +FBDEV_SUBDIRS = fbdev +endif + +if KDRIVELINUX +LINUX_SUBDIRS = linux +endif + +SUBDIRS = \ + src \ + $(LINUX_SUBDIRS) \ + $(FBDEV_SUBDIRS) \ + $(VESA_SUBDIRS) + +DIST_SUBDIRS = vesa fbdev src linux diff --git a/kdrive/fbdev/Makefile.am b/kdrive/fbdev/Makefile.am new file mode 100644 index 0000000..da31e2e --- /dev/null +++ b/kdrive/fbdev/Makefile.am @@ -0,0 +1,28 @@ +AM_CPPFLAGS = \ + @KDRIVE_INCS@ \ + @KDRIVE_CFLAGS@ + +noinst_LIBRARIES = libfbdev.a + +bin_PROGRAMS = Xfbdev + +libfbdev_a_SOURCES = \ + fbdev.c \ + fbdev.h + +Xfbdev_SOURCES = \ + fbinit.c + +Xfbdev_LDADD = \ + libfbdev.a \ + @KDRIVE_LIBS@ \ + @XSERVER_LIBS@ + +Xfbdev_DEPENDENCIES = \ + libfbdev.a @KDRIVE_LIBS@ + +install-exec-hook: +if INSTALL_SETUID + chown root $(DESTDIR)$(bindir)/Xfbdev + chmod u+s $(DESTDIR)$(bindir)/Xfbdev +endif diff --git a/kdrive/fbdev/fbdev.c b/kdrive/fbdev/fbdev.c new file mode 100644 index 0000000..ae89381 --- /dev/null +++ b/kdrive/fbdev/fbdev.c @@ -0,0 +1,784 @@ +/* + * + * Copyright © 1999 Keith Packard + * + * 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, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD 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_CONFIG_H +#include +#endif +#include "fbdev.h" +#include + +#include + +extern int KdTsPhyScreen; + +const char *fbdevDevicePath = NULL; + +static Bool fbdevMapFramebuffer(KdScreenInfo * screen); + +static Bool fbdevInitialize(KdCardInfo * card, FbdevPriv * priv) +{ + unsigned long off; + + if (fbdevDevicePath == NULL) + fbdevDevicePath = "/dev/fb0"; + + if ((priv->fd = open(fbdevDevicePath, O_RDWR)) < 0) { + ErrorF("Error opening framebuffer %s: %s\n", + fbdevDevicePath, strerror(errno)); + return FALSE; + } + + /* quiet valgrind */ + memset(&priv->fix, '\0', sizeof(priv->fix)); + if (ioctl(priv->fd, FBIOGET_FSCREENINFO, &priv->fix) < 0) { + perror("Error with /dev/fb ioctl FIOGET_FSCREENINFO"); + close(priv->fd); + return FALSE; + } + /* quiet valgrind */ + memset(&priv->var, '\0', sizeof(priv->var)); + if (ioctl(priv->fd, FBIOGET_VSCREENINFO, &priv->var) < 0) { + perror("Error with /dev/fb ioctl FIOGET_VSCREENINFO"); + close(priv->fd); + return FALSE; + } + + priv->fb_base = (char *) mmap((caddr_t) NULL, + priv->fix.smem_len, + PROT_READ | PROT_WRITE, + MAP_SHARED, priv->fd, 0); + + if (priv->fb_base == (char *) -1) { + perror("ERROR: mmap framebuffer fails!"); + close(priv->fd); + return FALSE; + } + off = (unsigned long) priv->fix.smem_start % (unsigned long) getpagesize(); + priv->fb = priv->fb_base + off; + return TRUE; +} + +Bool fbdevCardInit(KdCardInfo * card) +{ + FbdevPriv *priv; + + priv = malloc(sizeof(FbdevPriv)); + if (!priv) + return FALSE; + + if (!fbdevInitialize(card, priv)) { + free(priv); + return FALSE; + } + card->driver = priv; + + return TRUE; +} + +static Pixel fbdevMakeContig(Pixel orig, Pixel others) +{ + Pixel low; + + low = lowbit(orig) >> 1; + while (low && (others & low) == 0) { + orig |= low; + low >>= 1; + } + return orig; +} + +static Bool fbdevModeSupported(KdScreenInfo * screen, const KdMonitorTiming * t) +{ + return TRUE; +} + +static void +fbdevConvertMonitorTiming(const KdMonitorTiming * t, + struct fb_var_screeninfo *var) +{ + memset(var, 0, sizeof(struct fb_var_screeninfo)); + + var->xres = t->horizontal; + var->yres = t->vertical; + var->xres_virtual = t->horizontal; + var->yres_virtual = t->vertical; + var->xoffset = 0; + var->yoffset = 0; + var->pixclock = t->clock ? 1000000000 / t->clock : 0; + var->left_margin = t->hbp; + var->right_margin = t->hfp; + var->upper_margin = t->vbp; + var->lower_margin = t->vfp; + var->hsync_len = t->hblank - t->hfp - t->hbp; + var->vsync_len = t->vblank - t->vfp - t->vbp; + + var->sync = 0; + var->vmode = 0; + + if (t->hpol == KdSyncPositive) + var->sync |= FB_SYNC_HOR_HIGH_ACT; + if (t->vpol == KdSyncPositive) + var->sync |= FB_SYNC_VERT_HIGH_ACT; +} + +static Bool fbdevScreenInitialize(KdScreenInfo * screen, FbdevScrPriv * scrpriv) +{ + FbdevPriv *priv = screen->card->driver; + Pixel allbits; + int depth; + Bool gray; + struct fb_var_screeninfo var; + const KdMonitorTiming *t; + int k; + + k = ioctl(priv->fd, FBIOGET_VSCREENINFO, &var); + + if (!screen->width || !screen->height) { + if (k >= 0) { + screen->width = var.xres; + screen->height = var.yres; + } else { + screen->width = 1024; + screen->height = 768; + } + screen->rate = 103; /* FIXME: should get proper value from fb driver */ + } + if (!screen->fb.depth) { + if (k >= 0) + screen->fb.depth = var.bits_per_pixel; + else + screen->fb.depth = 16; + } + + if ((screen->width != var.xres) || (screen->height != var.yres)) { + t = KdFindMode(screen, fbdevModeSupported); + screen->rate = t->rate; + screen->width = t->horizontal; + screen->height = t->vertical; + + /* Now try setting the mode */ + if (k < 0 || (t->horizontal != var.xres || t->vertical != var.yres)) + fbdevConvertMonitorTiming(t, &var); + } + + var.activate = FB_ACTIVATE_NOW; + var.bits_per_pixel = screen->fb.depth; + var.nonstd = 0; + var.grayscale = 0; + + k = ioctl(priv->fd, FBIOPUT_VSCREENINFO, &var); + + if (k < 0) { + fprintf(stderr, "error: %s\n", strerror(errno)); + return FALSE; + } + + /* Re-get the "fixed" parameters since they might have changed */ + k = ioctl(priv->fd, FBIOGET_FSCREENINFO, &priv->fix); + if (k < 0) + perror("FBIOGET_FSCREENINFO"); + + /* Now get the new screeninfo */ + ioctl(priv->fd, FBIOGET_VSCREENINFO, &priv->var); + depth = priv->var.bits_per_pixel; + gray = priv->var.grayscale; + + /* Calculate fix.line_length if it's zero */ + if (!priv->fix.line_length) + priv->fix.line_length = (priv->var.xres_virtual * depth + 7) / 8; + + switch (priv->fix.visual) { + case FB_VISUAL_PSEUDOCOLOR: + if (gray) { + screen->fb.visuals = (1 << StaticGray); + /* could also support GrayScale, but what's the point? */ + } else { + screen->fb.visuals = ((1 << StaticGray) | + (1 << GrayScale) | + (1 << StaticColor) | + (1 << PseudoColor) | + (1 << TrueColor) | + (1 << DirectColor)); + } + screen->fb.blueMask = 0x00; + screen->fb.greenMask = 0x00; + screen->fb.redMask = 0x00; + break; + case FB_VISUAL_STATIC_PSEUDOCOLOR: + if (gray) { + screen->fb.visuals = (1 << StaticGray); + } else { + screen->fb.visuals = (1 << StaticColor); + } + screen->fb.blueMask = 0x00; + screen->fb.greenMask = 0x00; + screen->fb.redMask = 0x00; + break; + case FB_VISUAL_TRUECOLOR: + case FB_VISUAL_DIRECTCOLOR: + screen->fb.visuals = (1 << TrueColor); +#define Mask(o,l) (((1 << l) - 1) << o) + screen->fb.redMask = + Mask(priv->var.red.offset, priv->var.red.length); + screen->fb.greenMask = + Mask(priv->var.green.offset, priv->var.green.length); + screen->fb.blueMask = + Mask(priv->var.blue.offset, priv->var.blue.length); + /* + * This is a kludge so that Render will work -- fill in the gaps + * in the pixel + */ + screen->fb.redMask = fbdevMakeContig(screen->fb.redMask, + screen->fb. + greenMask | screen-> + fb.blueMask); + + screen->fb.greenMask = + fbdevMakeContig(screen->fb.greenMask, + screen->fb.redMask | screen->fb. + blueMask); + + screen->fb.blueMask = fbdevMakeContig(screen->fb.blueMask, + screen->fb.redMask | + screen->fb. + greenMask); + + allbits = + screen->fb.redMask | screen->fb.greenMask | screen-> + fb.blueMask; + depth = 32; + while (depth && !(allbits & (1 << (depth - 1)))) + depth--; + break; + default: + return FALSE; + break; + } + screen->fb.depth = depth; + screen->fb.bitsPerPixel = priv->var.bits_per_pixel; + + scrpriv->randr = screen->randr; + + return fbdevMapFramebuffer(screen); +} + +Bool fbdevScreenInit(KdScreenInfo * screen) +{ + FbdevScrPriv *scrpriv; + + scrpriv = calloc(1, sizeof(FbdevScrPriv)); + if (!scrpriv) + return FALSE; + screen->driver = scrpriv; + if (!fbdevScreenInitialize(screen, scrpriv)) { + screen->driver = 0; + free(scrpriv); + return FALSE; + } + return TRUE; +} + +static void *fbdevWindowLinear(ScreenPtr pScreen, + CARD32 row, + CARD32 offset, int mode, CARD32 * size, void *closure) +{ + KdScreenPriv(pScreen); + FbdevPriv *priv = pScreenPriv->card->driver; + + if (!pScreenPriv->enabled) + return 0; + *size = priv->fix.line_length; + return (CARD8 *) priv->fb + row * priv->fix.line_length + offset; +} + +static Bool fbdevMapFramebuffer(KdScreenInfo * screen) +{ + FbdevScrPriv *scrpriv = screen->driver; + KdMouseMatrix m; + FbdevPriv *priv = screen->card->driver; + + if (scrpriv->randr != RR_Rotate_0 || + priv->fix.type != FB_TYPE_PACKED_PIXELS) + scrpriv->shadow = TRUE; + else + scrpriv->shadow = FALSE; + + KdComputeMouseMatrix(&m, scrpriv->randr, screen->width, screen->height); + + KdSetMouseMatrix(&m); + + screen->width = priv->var.xres; + screen->height = priv->var.yres; + screen->memory_base = (CARD8 *) (priv->fb); + screen->memory_size = priv->fix.smem_len; + + if (scrpriv->shadow) { + if (!KdShadowFbAlloc(screen, + scrpriv-> + randr & (RR_Rotate_90 | RR_Rotate_270))) + return FALSE; + screen->off_screen_base = screen->memory_size; + } else { + screen->fb.byteStride = priv->fix.line_length; + screen->fb.pixelStride = (priv->fix.line_length * 8 / + priv->var.bits_per_pixel); + screen->fb.frameBuffer = (CARD8 *) (priv->fb); + screen->off_screen_base = + screen->fb.byteStride * screen->height; + } + + return TRUE; +} + +static void fbdevSetScreenSizes(ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + FbdevScrPriv *scrpriv = screen->driver; + FbdevPriv *priv = screen->card->driver; + + if (scrpriv->randr & (RR_Rotate_0 | RR_Rotate_180)) { + pScreen->width = priv->var.xres; + pScreen->height = priv->var.yres; + pScreen->mmWidth = screen->width_mm; + pScreen->mmHeight = screen->height_mm; + } else { + pScreen->width = priv->var.yres; + pScreen->height = priv->var.xres; + pScreen->mmWidth = screen->height_mm; + pScreen->mmHeight = screen->width_mm; + } +} + +static Bool fbdevUnmapFramebuffer(KdScreenInfo * screen) +{ + KdShadowFbFree(screen); + return TRUE; +} + +static Bool fbdevSetShadow(ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + FbdevScrPriv *scrpriv = screen->driver; + FbdevPriv *priv = screen->card->driver; + ShadowUpdateProc update; + ShadowWindowProc window; + int useYX = 0; + +#ifdef __arm__ + /* Use variant copy routines that always read left to right in the + shadow framebuffer. Reading vertical strips is exceptionally + slow on XScale due to cache effects. */ + useYX = 1; +#endif + + window = fbdevWindowLinear; + update = 0; + + if (priv->fix.type != FB_TYPE_PACKED_PIXELS) + FatalError("Unsupported frame buffer type %u\n", priv->fix.type); + + if (scrpriv->randr) + if (priv->var.bits_per_pixel == 16) { + switch (scrpriv->randr) { + case RR_Rotate_90: + if (useYX) + update = shadowUpdateRotate16_90YX; + else + update = shadowUpdateRotate16_90; + break; + case RR_Rotate_180: + update = shadowUpdateRotate16_180; + break; + case RR_Rotate_270: + if (useYX) + update = shadowUpdateRotate16_270YX; + else + update = shadowUpdateRotate16_270; + break; + default: + update = shadowUpdateRotate16; + break; + } + } else + update = shadowUpdateRotatePacked; + else + update = shadowUpdatePacked; + return KdShadowSet(pScreen, scrpriv->randr, update, window); +} + +static Bool fbdevRandRGetInfo(ScreenPtr pScreen, Rotation * rotations) +{ + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + FbdevScrPriv *scrpriv = screen->driver; + RRScreenSizePtr pSize; + Rotation randr; + int n; + + *rotations = RR_Rotate_All | RR_Reflect_All; + + for (n = 0; n < pScreen->numDepths; n++) + if (pScreen->allowedDepths[n].numVids) + break; + if (n == pScreen->numDepths) + return FALSE; + + pSize = RRRegisterSize(pScreen, + screen->width, + screen->height, + screen->width_mm, screen->height_mm); + + randr = KdSubRotation(scrpriv->randr, screen->randr); + + RRSetCurrentConfig(pScreen, randr, 0, pSize); + + return TRUE; +} + +static Bool +fbdevRandRSetConfig(ScreenPtr pScreen, + Rotation randr, int rate, RRScreenSizePtr pSize) +{ + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + FbdevScrPriv *scrpriv = screen->driver; + Bool wasEnabled = pScreenPriv->enabled; + FbdevScrPriv oldscr; + int oldwidth; + int oldheight; + int oldmmwidth; + int oldmmheight; + int newwidth, newheight, newmmwidth, newmmheight; + + if (screen->randr & (RR_Rotate_0 | RR_Rotate_180)) { + newwidth = pSize->width; + newheight = pSize->height; + newmmwidth = pSize->mmWidth; + newmmheight = pSize->mmHeight; + } else { + newwidth = pSize->height; + newheight = pSize->width; + newmmwidth = pSize->mmHeight; + newmmheight = pSize->mmWidth; + } + + if (wasEnabled) + KdDisableScreen(pScreen); + + oldscr = *scrpriv; + + oldwidth = screen->width; + oldheight = screen->height; + oldmmwidth = pScreen->mmWidth; + oldmmheight = pScreen->mmHeight; + + /* + * Set new configuration + */ + + scrpriv->randr = KdAddRotation(screen->randr, randr); + + pScreen->width = newwidth; + pScreen->height = newheight; + pScreen->mmWidth = newmmwidth; + pScreen->mmHeight = newmmheight; + + fbdevUnmapFramebuffer(screen); + + if (!fbdevMapFramebuffer(screen)) + goto bail4; + + KdShadowUnset(screen->pScreen); + + if (!fbdevSetShadow(screen->pScreen)) + goto bail4; + + fbdevSetScreenSizes(screen->pScreen); + + /* + * Set frame buffer mapping + */ + (*pScreen->ModifyPixmapHeader) (fbGetScreenPixmap(pScreen), + pScreen->width, + pScreen->height, + screen->fb.depth, + screen->fb.bitsPerPixel, + screen->fb.byteStride, + screen->fb.frameBuffer); + + /* set the subpixel order */ + + KdSetSubpixelOrder(pScreen, scrpriv->randr); + if (wasEnabled) + KdEnableScreen(pScreen); + + return TRUE; + + bail4: + fbdevUnmapFramebuffer(screen); + *scrpriv = oldscr; + fbdevMapFramebuffer(screen); + pScreen->width = oldwidth; + pScreen->height = oldheight; + pScreen->mmWidth = oldmmwidth; + pScreen->mmHeight = oldmmheight; + + if (wasEnabled) + KdEnableScreen(pScreen); + return FALSE; +} + +static Bool fbdevRandRInit(ScreenPtr pScreen) +{ + rrScrPrivPtr pScrPriv; + + if (!RRScreenInit(pScreen)) + return FALSE; + + pScrPriv = rrGetScrPriv(pScreen); + pScrPriv->rrGetInfo = fbdevRandRGetInfo; + pScrPriv->rrSetConfig = fbdevRandRSetConfig; + return TRUE; +} + +static Bool fbdevCreateColormap(ColormapPtr pmap) +{ + ScreenPtr pScreen = pmap->pScreen; + KdScreenPriv(pScreen); + FbdevPriv *priv = pScreenPriv->card->driver; + VisualPtr pVisual; + int i; + int nent; + xColorItem *pdefs; + + switch (priv->fix.visual) { + case FB_VISUAL_STATIC_PSEUDOCOLOR: + pVisual = pmap->pVisual; + nent = pVisual->ColormapEntries; + pdefs = malloc(nent * sizeof(xColorItem)); + if (!pdefs) + return FALSE; + for (i = 0; i < nent; i++) + pdefs[i].pixel = i; + fbdevGetColors(pScreen, nent, pdefs); + for (i = 0; i < nent; i++) { + pmap->red[i].co.local.red = pdefs[i].red; + pmap->red[i].co.local.green = pdefs[i].green; + pmap->red[i].co.local.blue = pdefs[i].blue; + } + free(pdefs); + return TRUE; + default: + return fbInitializeColormap(pmap); + } +} + +Bool fbdevInitScreen(ScreenPtr pScreen) +{ + + pScreen->CreateColormap = fbdevCreateColormap; + return TRUE; +} + +Bool fbdevFinishInitScreen(ScreenPtr pScreen) +{ + if (!shadowSetup(pScreen)) + return FALSE; + + if (!fbdevRandRInit(pScreen)) + return FALSE; + + return TRUE; +} + +Bool fbdevCreateResources(ScreenPtr pScreen) +{ + return fbdevSetShadow(pScreen); +} + +void fbdevPreserve(KdCardInfo * card) +{ +} + +static int fbdevUpdateFbColormap(FbdevPriv *priv, int minidx, int maxidx) +{ + struct fb_cmap cmap; + + cmap.start = minidx; + cmap.len = maxidx - minidx + 1; + cmap.red = &priv->red[minidx]; + cmap.green = &priv->green[minidx]; + cmap.blue = &priv->blue[minidx]; + cmap.transp = 0; + + return ioctl(priv->fd, FBIOPUTCMAP, &cmap); +} + +Bool fbdevEnable(ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + FbdevPriv *priv = pScreenPriv->card->driver; + int k; + + priv->var.activate = FB_ACTIVATE_NOW | FB_CHANGE_CMAP_VBL; + + /* display it on the LCD */ + k = ioctl(priv->fd, FBIOPUT_VSCREENINFO, &priv->var); + if (k < 0) { + perror("FBIOPUT_VSCREENINFO"); + return FALSE; + } + + if (priv->fix.visual == FB_VISUAL_DIRECTCOLOR) { + int i; + + for (i = 0; + i < (1 << priv->var.red.length) || + i < (1 << priv->var.green.length) || + i < (1 << priv->var.blue.length); i++) { + priv->red[i] = + i * 65535 / ((1 << priv->var.red.length) - 1); + priv->green[i] = + i * 65535 / ((1 << priv->var.green.length) - 1); + priv->blue[i] = + i * 65535 / ((1 << priv->var.blue.length) - 1); + } + i--; + fbdevUpdateFbColormap(priv, 0, i); + } + return TRUE; +} + +Bool fbdevDPMS(ScreenPtr pScreen, int mode) +{ + KdScreenPriv(pScreen); + FbdevPriv *priv = pScreenPriv->card->driver; + static int oldmode = -1; + + if (mode == oldmode) + return TRUE; +#ifdef FBIOPUT_POWERMODE + if (ioctl(priv->fd, FBIOPUT_POWERMODE, &mode) >= 0) { + oldmode = mode; + return TRUE; + } +#endif +#ifdef FBIOBLANK + if (ioctl(priv->fd, FBIOBLANK, mode ? mode + 1 : 0) >= 0) { + oldmode = mode; + return TRUE; + } +#endif + return FALSE; +} + +void fbdevDisable(ScreenPtr pScreen) +{ +} + +void fbdevRestore(KdCardInfo * card) +{ +} + +void fbdevScreenFini(KdScreenInfo * screen) +{ +} + +void fbdevCardFini(KdCardInfo * card) +{ + FbdevPriv *priv = card->driver; + + munmap(priv->fb_base, priv->fix.smem_len); + close(priv->fd); + free(priv); +} + +/* + * Retrieve actual colormap and return selected n entries in pdefs. + */ + +void fbdevGetColors(ScreenPtr pScreen, int n, xColorItem * pdefs) +{ + KdScreenPriv(pScreen); + FbdevPriv *priv = pScreenPriv->card->driver; + struct fb_cmap cmap; + int p; + int k; + int min, max; + + min = 256; + max = 0; + for (k = 0; k < n; k++) { + if (pdefs[k].pixel < min) + min = pdefs[k].pixel; + if (pdefs[k].pixel > max) + max = pdefs[k].pixel; + } + cmap.start = min; + cmap.len = max - min + 1; + cmap.red = &priv->red[min]; + cmap.green = &priv->green[min]; + cmap.blue = &priv->blue[min]; + cmap.transp = 0; + k = ioctl(priv->fd, FBIOGETCMAP, &cmap); + if (k < 0) { + perror("can't get colormap"); + return; + } + while (n--) { + p = pdefs->pixel; + pdefs->red = priv->red[p]; + pdefs->green = priv->green[p]; + pdefs->blue = priv->blue[p]; + pdefs++; + } +} + +/* + * Change colormap by updating n entries described in pdefs. + */ +void fbdevPutColors(ScreenPtr pScreen, int n, xColorItem * pdefs) +{ + KdScreenPriv(pScreen); + FbdevPriv *priv = pScreenPriv->card->driver; + int p; + int min, max; + + min = 256; + max = 0; + while (n--) { + p = pdefs->pixel; + priv->red[p] = pdefs->red; + priv->green[p] = pdefs->green; + priv->blue[p] = pdefs->blue; + if (p < min) + min = p; + if (p > max) + max = p; + pdefs++; + } + + fbdevUpdateFbColormap(priv, min, max); +} diff --git a/kdrive/fbdev/fbdev.h b/kdrive/fbdev/fbdev.h new file mode 100644 index 0000000..ae4cb91 --- /dev/null +++ b/kdrive/fbdev/fbdev.h @@ -0,0 +1,80 @@ +/* + * + * Copyright © 1999 Keith Packard + * + * 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, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _FBDEV_H_ +#define _FBDEV_H_ +#include +#include +#include +#include +#include "kdrive.h" + +#include "randrstr.h" + +typedef struct _fbdevPriv { + struct fb_var_screeninfo var; + struct fb_fix_screeninfo fix; + __u16 red[256]; + __u16 green[256]; + __u16 blue[256]; + int fd; + char *fb; + char *fb_base; +} FbdevPriv; + +typedef struct _fbdevScrPriv { + Rotation randr; + Bool shadow; +} FbdevScrPriv; + +extern const char *fbdevDevicePath; + +Bool fbdevCardInit(KdCardInfo * card); + +Bool fbdevScreenInit(KdScreenInfo * screen); + +Bool fbdevInitScreen(ScreenPtr pScreen); + +Bool fbdevFinishInitScreen(ScreenPtr pScreen); + +Bool fbdevCreateResources(ScreenPtr pScreen); + +void fbdevPreserve(KdCardInfo * card); + +Bool fbdevEnable(ScreenPtr pScreen); + +Bool fbdevDPMS(ScreenPtr pScreen, int mode); + +void fbdevDisable(ScreenPtr pScreen); + +void fbdevRestore(KdCardInfo * card); + +void fbdevScreenFini(KdScreenInfo * screen); + +void fbdevCardFini(KdCardInfo * card); + +void fbdevGetColors(ScreenPtr pScreen, int n, xColorItem * pdefs); + +void fbdevPutColors(ScreenPtr pScreen, int n, xColorItem * pdefs); + +#endif /* _FBDEV_H_ */ diff --git a/kdrive/fbdev/fbinit.c b/kdrive/fbdev/fbinit.c new file mode 100644 index 0000000..7be0190 --- /dev/null +++ b/kdrive/fbdev/fbinit.c @@ -0,0 +1,100 @@ +/* + * + * Copyright © 1999 Keith Packard + * + * 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, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD 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_CONFIG_H +#include +#endif +#include + +static const KdCardFuncs fbdevFuncs = { + fbdevCardInit, /* cardinit */ + fbdevScreenInit, /* scrinit */ + fbdevInitScreen, /* initScreen */ + fbdevFinishInitScreen, /* finishInitScreen */ + fbdevCreateResources, /* createRes */ + fbdevPreserve, /* preserve */ + fbdevEnable, /* enable */ + fbdevDPMS, /* dpms */ + fbdevDisable, /* disable */ + fbdevRestore, /* restore */ + fbdevScreenFini, /* scrfini */ + fbdevCardFini, /* cardfini */ + + 0, /* initCursor */ + 0, /* enableCursor */ + 0, /* disableCursor */ + 0, /* finiCursor */ + 0, /* recolorCursor */ + + 0, /* initAccel */ + 0, /* enableAccel */ + 0, /* disableAccel */ + 0, /* finiAccel */ + + fbdevGetColors, /* getColors */ + fbdevPutColors, /* putColors */ +}; + +void InitCard(char *name) +{ + KdCardInfoAdd(&fbdevFuncs, 0); +} + +void InitOutput(ScreenInfo * pScreenInfo, int argc, char **argv) +{ + KdInitOutput(pScreenInfo, argc, argv); +} + +void InitInput(int argc, char **argv) +{ + KdInitInput(&LinuxMouseFuncs, &LinuxKeyboardFuncs); +} + +void ddxUseMsg(void) +{ + KdUseMsg(); + ErrorF("\nXfbdev Device Usage:\n"); + ErrorF + ("-fb path Framebuffer device to use. Defaults to /dev/fb0\n"); + ErrorF("\n"); +} + +int ddxProcessArgument(int argc, char **argv, int i) +{ + + if (!strcmp(argv[i], "-version")) { + kdVersion("Xfbdev"); + exit(0); + } + + if (!strcmp(argv[i], "-fb")) { + if (i + 1 < argc) { + fbdevDevicePath = argv[i + 1]; + return 2; + } + UseMsg(); + exit(1); + } + + return KdProcessArgument(argc, argv, i); +} diff --git a/kdrive/linux/Makefile.am b/kdrive/linux/Makefile.am new file mode 100644 index 0000000..9d728e7 --- /dev/null +++ b/kdrive/linux/Makefile.am @@ -0,0 +1,20 @@ +AM_CPPFLAGS = \ + @KDRIVE_INCS@ \ + @KDRIVE_CFLAGS@ + +AM_CFLAGS = -DHAVE_DIX_CONFIG_H + +noinst_LIBRARIES = liblinux.a + +KDRIVE_HW_SOURCES = \ + keyboard.c \ + linux.c + +liblinux_a_SOURCES = \ + mouse.c \ + $(KDRIVE_HW_SOURCES) + +liblinux_a_DEPENDENCIES = \ + keyboard.c \ + linux.c \ + mouse.c diff --git a/kdrive/linux/keyboard.c b/kdrive/linux/keyboard.c new file mode 100644 index 0000000..8d75626 --- /dev/null +++ b/kdrive/linux/keyboard.c @@ -0,0 +1,469 @@ +/* + * + * Copyright © 1999 Keith Packard + * + * 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, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD 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_CONFIG_H +#include +#endif +#include "kdrive.h" +#include "kkeymap.h" +#include +#include +#define XK_PUBLISHING +#include +#include +#include + +extern int LinuxConsoleFd; + +static const KeySym linux_to_x[256] = { + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + XK_BackSpace, XK_Tab, XK_Linefeed, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, XK_Escape, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + XK_space, XK_exclam, XK_quotedbl, XK_numbersign, + XK_dollar, XK_percent, XK_ampersand, XK_apostrophe, + XK_parenleft, XK_parenright, XK_asterisk, XK_plus, + XK_comma, XK_minus, XK_period, XK_slash, + XK_0, XK_1, XK_2, XK_3, + XK_4, XK_5, XK_6, XK_7, + XK_8, XK_9, XK_colon, XK_semicolon, + XK_less, XK_equal, XK_greater, XK_question, + XK_at, XK_A, XK_B, XK_C, + XK_D, XK_E, XK_F, XK_G, + XK_H, XK_I, XK_J, XK_K, + XK_L, XK_M, XK_N, XK_O, + XK_P, XK_Q, XK_R, XK_S, + XK_T, XK_U, XK_V, XK_W, + XK_X, XK_Y, XK_Z, XK_bracketleft, + XK_backslash, XK_bracketright, XK_asciicircum, XK_underscore, + XK_grave, XK_a, XK_b, XK_c, + XK_d, XK_e, XK_f, XK_g, + XK_h, XK_i, XK_j, XK_k, + XK_l, XK_m, XK_n, XK_o, + XK_p, XK_q, XK_r, XK_s, + XK_t, XK_u, XK_v, XK_w, + XK_x, XK_y, XK_z, XK_braceleft, + XK_bar, XK_braceright, XK_asciitilde, XK_BackSpace, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + XK_nobreakspace, XK_exclamdown, XK_cent, XK_sterling, + XK_currency, XK_yen, XK_brokenbar, XK_section, + XK_diaeresis, XK_copyright, XK_ordfeminine, XK_guillemotleft, + XK_notsign, XK_hyphen, XK_registered, XK_macron, + XK_degree, XK_plusminus, XK_twosuperior, XK_threesuperior, + XK_acute, XK_mu, XK_paragraph, XK_periodcentered, + XK_cedilla, XK_onesuperior, XK_masculine, XK_guillemotright, + XK_onequarter, XK_onehalf, XK_threequarters, XK_questiondown, + XK_Agrave, XK_Aacute, XK_Acircumflex, XK_Atilde, + XK_Adiaeresis, XK_Aring, XK_AE, XK_Ccedilla, + XK_Egrave, XK_Eacute, XK_Ecircumflex, XK_Ediaeresis, + XK_Igrave, XK_Iacute, XK_Icircumflex, XK_Idiaeresis, + XK_ETH, XK_Ntilde, XK_Ograve, XK_Oacute, + XK_Ocircumflex, XK_Otilde, XK_Odiaeresis, XK_multiply, + XK_Ooblique, XK_Ugrave, XK_Uacute, XK_Ucircumflex, + XK_Udiaeresis, XK_Yacute, XK_THORN, XK_ssharp, + XK_agrave, XK_aacute, XK_acircumflex, XK_atilde, + XK_adiaeresis, XK_aring, XK_ae, XK_ccedilla, + XK_egrave, XK_eacute, XK_ecircumflex, XK_ediaeresis, + XK_igrave, XK_iacute, XK_icircumflex, XK_idiaeresis, + XK_eth, XK_ntilde, XK_ograve, XK_oacute, + XK_ocircumflex, XK_otilde, XK_odiaeresis, XK_division, + XK_oslash, XK_ugrave, XK_uacute, XK_ucircumflex, + XK_udiaeresis, XK_yacute, XK_thorn, XK_ydiaeresis +}; + +static unsigned char tbl[KD_MAX_WIDTH] = { + 0, + 1 << KG_SHIFT, + (1 << KG_ALTGR), + (1 << KG_ALTGR) | (1 << KG_SHIFT) +}; + +static void readKernelMapping(void) +{ + KeySym *k; + int i, j; + struct kbentry kbe; + int minKeyCode, maxKeyCode; + int row; + + minKeyCode = NR_KEYS; + maxKeyCode = 0; + row = 0; + for (i = 0; i < NR_KEYS && row < KD_MAX_LENGTH; ++i) { + kbe.kb_index = i; + + k = kdKeymap + row * KD_MAX_WIDTH; + + for (j = 0; j < KD_MAX_WIDTH; ++j) { + unsigned short kval; + + k[j] = NoSymbol; + + kbe.kb_table = tbl[j]; + kbe.kb_value = 0; + if (ioctl(LinuxConsoleFd, KDGKBENT, &kbe)) + continue; + + kval = KVAL(kbe.kb_value); + switch (KTYP(kbe.kb_value)) { + case KT_LATIN: + case KT_LETTER: + k[j] = linux_to_x[kval]; + break; + + case KT_FN: + if (kval <= 19) + k[j] = XK_F1 + kval; + else + switch (kbe.kb_value) { + case K_FIND: + k[j] = XK_Home; /* or XK_Find */ + break; + case K_INSERT: + k[j] = XK_Insert; + break; + case K_REMOVE: + k[j] = XK_Delete; + break; + case K_SELECT: + k[j] = XK_End; /* or XK_Select */ + break; + case K_PGUP: + k[j] = XK_Prior; + break; + case K_PGDN: + k[j] = XK_Next; + break; + case K_HELP: + k[j] = XK_Help; + break; + case K_DO: + k[j] = XK_Execute; + break; + case K_PAUSE: + k[j] = XK_Pause; + break; + case K_MACRO: + k[j] = XK_Menu; + break; + default: + break; + } + break; + + case KT_SPEC: + switch (kbe.kb_value) { + case K_ENTER: + k[j] = XK_Return; + break; + case K_BREAK: + k[j] = XK_Break; + break; + case K_CAPS: + k[j] = XK_Caps_Lock; + break; + case K_NUM: + k[j] = XK_Num_Lock; + break; + case K_HOLD: + k[j] = XK_Scroll_Lock; + break; + case K_COMPOSE: + k[j] = XK_Multi_key; + break; + default: + break; + } + break; + + case KT_PAD: + switch (kbe.kb_value) { + case K_PPLUS: + k[j] = XK_KP_Add; + break; + case K_PMINUS: + k[j] = XK_KP_Subtract; + break; + case K_PSTAR: + k[j] = XK_KP_Multiply; + break; + case K_PSLASH: + k[j] = XK_KP_Divide; + break; + case K_PENTER: + k[j] = XK_KP_Enter; + break; + case K_PCOMMA: + k[j] = XK_KP_Separator; + break; + case K_PDOT: + k[j] = XK_KP_Decimal; + break; + case K_PPLUSMINUS: + k[j] = XK_KP_Subtract; + break; + default: + if (kval <= 9) + k[j] = XK_KP_0 + kval; + break; + } + break; + + /* + * KT_DEAD keys are for accelerated diacritical creation. + */ + case KT_DEAD: + switch (kbe.kb_value) { + case K_DGRAVE: + k[j] = XK_dead_grave; + break; + case K_DACUTE: + k[j] = XK_dead_acute; + break; + case K_DCIRCM: + k[j] = XK_dead_circumflex; + break; + case K_DTILDE: + k[j] = XK_dead_tilde; + break; + case K_DDIERE: + k[j] = XK_dead_diaeresis; + break; + } + break; + + case KT_CUR: + switch (kbe.kb_value) { + case K_DOWN: + k[j] = XK_Down; + break; + case K_LEFT: + k[j] = XK_Left; + break; + case K_RIGHT: + k[j] = XK_Right; + break; + case K_UP: + k[j] = XK_Up; + break; + } + break; + + case KT_SHIFT: + switch (kbe.kb_value) { + case K_ALTGR: + k[j] = XK_Mode_switch; + break; + case K_ALT: + k[j] = (kbe.kb_index == 0x64 ? + XK_Alt_R : XK_Alt_L); + break; + case K_CTRL: + k[j] = (kbe.kb_index == 0x61 ? + XK_Control_R : XK_Control_L); + break; + case K_CTRLL: + k[j] = XK_Control_L; + break; + case K_CTRLR: + k[j] = XK_Control_R; + break; + case K_SHIFT: + k[j] = (kbe.kb_index == 0x36 ? + XK_Shift_R : XK_Shift_L); + break; + case K_SHIFTL: + k[j] = XK_Shift_L; + break; + case K_SHIFTR: + k[j] = XK_Shift_R; + break; + default: + break; + } + break; + + /* + * KT_ASCII keys accumulate a 3 digit decimal number that gets + * emitted when the shift state changes. We can't emulate that. + */ + case KT_ASCII: + break; + + case KT_LOCK: + if (kbe.kb_value == K_SHIFTLOCK) + k[j] = XK_Shift_Lock; + break; + +#ifdef KT_X + case KT_X: + /* depends on new keyboard symbols in file linux/keyboard.h */ + if (kbe.kb_value == K_XMENU) + k[j] = XK_Menu; + if (kbe.kb_value == K_XTELEPHONE) + k[j] = XK_telephone; + break; +#endif +#ifdef KT_XF + case KT_XF: + /* special linux keysyms which map directly to XF86 keysyms */ + k[j] = (kbe.kb_value & 0xFF) + 0x1008FF00; + break; +#endif + + default: + break; + } + if (i < minKeyCode) + minKeyCode = i; + if (i > maxKeyCode) + maxKeyCode = i; + } + + if (minKeyCode == NR_KEYS) + continue; + + if (k[3] == k[2]) + k[3] = NoSymbol; + if (k[2] == k[1]) + k[2] = NoSymbol; + if (k[1] == k[0]) + k[1] = NoSymbol; + if (k[0] == k[2] && k[1] == k[3]) + k[2] = k[3] = NoSymbol; + if (k[3] == k[0] && k[2] == k[1] && k[2] == NoSymbol) + k[3] = NoSymbol; + row++; + } + kdMinScanCode = minKeyCode; + kdMaxScanCode = maxKeyCode; +} + +static void LinuxKeyboardLoad(void) +{ + readKernelMapping(); +} + +static void LinuxKeyboardRead(int fd, void *closure) +{ + unsigned char buf[256], *b; + int n; + + while ((n = read(fd, buf, sizeof(buf))) > 0) { + b = buf; + while (n--) { + KdEnqueueKeyboardEvent(b[0] & 0x7f, b[0] & 0x80); + b++; + } + } +} + +static int LinuxKbdTrans; +static struct termios LinuxTermios; +static int LinuxKbdType; + +static int LinuxKeyboardEnable(int fd, void *closure) +{ + struct termios nTty; + unsigned char buf[256]; + int n; + + ioctl(fd, KDGKBMODE, &LinuxKbdTrans); + tcgetattr(fd, &LinuxTermios); + + ioctl(fd, KDSKBMODE, K_MEDIUMRAW); + nTty = LinuxTermios; + nTty.c_iflag = (IGNPAR | IGNBRK) & (~PARMRK) & (~ISTRIP); + nTty.c_oflag = 0; + nTty.c_cflag = CREAD | CS8; + nTty.c_lflag = 0; + nTty.c_cc[VTIME] = 0; + nTty.c_cc[VMIN] = 1; + cfsetispeed(&nTty, 9600); + cfsetospeed(&nTty, 9600); + tcsetattr(fd, TCSANOW, &nTty); + /* + * Flush any pending keystrokes + */ + while ((n = read(fd, buf, sizeof(buf))) > 0) ; + return fd; +} + +static void LinuxKeyboardDisable(int fd, void *closure) +{ + ioctl(LinuxConsoleFd, KDSKBMODE, LinuxKbdTrans); + tcsetattr(LinuxConsoleFd, TCSANOW, &LinuxTermios); +} + +static int LinuxKeyboardInit(void) +{ + if (!LinuxKbdType) + LinuxKbdType = KdAllocInputType(); + + KdRegisterFd(LinuxKbdType, LinuxConsoleFd, LinuxKeyboardRead, 0); + LinuxKeyboardEnable(LinuxConsoleFd, 0); + KdRegisterFdEnableDisable(LinuxConsoleFd, + LinuxKeyboardEnable, LinuxKeyboardDisable); + return 1; +} + +static void LinuxKeyboardFini(void) +{ + LinuxKeyboardDisable(LinuxConsoleFd, 0); + KdUnregisterFds(LinuxKbdType, FALSE); +} + +static void LinuxKeyboardLeds(int leds) +{ + ioctl(LinuxConsoleFd, KDSETLED, leds & 7); +} + +static void LinuxKeyboardBell(int volume, int pitch, int duration) +{ + if (volume && pitch) { + ioctl(LinuxConsoleFd, KDMKTONE, + ((1193190 / pitch) & 0xffff) | + (((unsigned long)duration * volume / 50) << 16)); + + } +} + +const KdKeyboardFuncs LinuxKeyboardFuncs = { + LinuxKeyboardLoad, + LinuxKeyboardInit, + LinuxKeyboardLeds, + LinuxKeyboardBell, + LinuxKeyboardFini, + 3, +}; diff --git a/kdrive/linux/linux.c b/kdrive/linux/linux.c new file mode 100644 index 0000000..7a589cd --- /dev/null +++ b/kdrive/linux/linux.c @@ -0,0 +1,342 @@ +/* + * + * Copyright © 1999 Keith Packard + * + * 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, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD 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_CONFIG_H +#include +#endif +#include "kdrive.h" +#include +#include +#include +#include +#include +#include +#include +#include + +static int vtno; +int LinuxConsoleFd; +static int LinuxApmFd; +static int activeVT; +static Bool enabled; + +static void LinuxVTRequest(int sig) +{ + kdSwitchPending = TRUE; +} + +/* Check before chowning -- this avoids touching the file system */ +static void LinuxCheckChown(char *file) +{ + struct stat st; + __uid_t u; + __gid_t g; + + if (stat(file, &st) < 0) + return; + u = getuid(); + g = getgid(); + if (st.st_uid != u || st.st_gid != g) + chown(file, u, g); +} + +static int LinuxInit(void) +{ + int fd = -1; + LinuxApmFd = -1; + char vtname[11]; + struct vt_stat vts; + + LinuxConsoleFd = -1; + /* check if we're run with euid==0 */ + if (geteuid() != 0) { + FatalError("LinuxInit: Server must be suid root\n"); + } + + if (kdVirtualTerminal >= 0) + vtno = kdVirtualTerminal; + else { + if ((fd = open("/dev/tty0", O_WRONLY, 0)) < 0) { + FatalError("LinuxInit: Cannot open /dev/tty0 (%s)\n", + strerror(errno)); + } + if ((ioctl(fd, VT_OPENQRY, &vtno) < 0) || (vtno == -1)) { + FatalError("xf86OpenConsole: Cannot find a free VT\n"); + } + } + close(fd); + + sprintf(vtname, "/dev/tty%d", vtno); /* /dev/tty1-64 */ + + if ((LinuxConsoleFd = open(vtname, O_RDWR | O_NDELAY, 0)) < 0) { + FatalError("LinuxInit: Cannot open %s (%s)\n", + vtname, strerror(errno)); + } + + /* change ownership of the vt */ + LinuxCheckChown(vtname); + + /* + * the current VT device we're running on is not "console", we want + * to grab all consoles too + * + * Why is this needed? + */ + LinuxCheckChown("/dev/tty0"); + /* + * Linux doesn't switch to an active vt after the last close of a vt, + * so we do this ourselves by remembering which is active now. + */ + memset(&vts, '\0', sizeof(vts)); /* valgrind */ + if (ioctl(LinuxConsoleFd, VT_GETSTATE, &vts) == 0) { + activeVT = vts.v_active; + } + + return 1; +} + +static void LinuxSetSwitchMode(int mode) +{ + struct sigaction act; + struct vt_mode VT; + + if (ioctl(LinuxConsoleFd, VT_GETMODE, &VT) < 0) { + FatalError("LinuxInit: VT_GETMODE failed\n"); + } + + if (mode == VT_PROCESS) { + act.sa_handler = LinuxVTRequest; + sigemptyset(&act.sa_mask); + act.sa_flags = 0; + sigaction(SIGUSR1, &act, 0); + + VT.mode = mode; + VT.relsig = SIGUSR1; + VT.acqsig = SIGUSR1; + } else { + act.sa_handler = SIG_IGN; + sigemptyset(&act.sa_mask); + act.sa_flags = 0; + sigaction(SIGUSR1, &act, 0); + + VT.mode = mode; + VT.relsig = 0; + VT.acqsig = 0; + } + if (ioctl(LinuxConsoleFd, VT_SETMODE, &VT) < 0) { + FatalError("LinuxInit: VT_SETMODE failed\n"); + } +} + +static void +LinuxApmBlock(pointer blockData, OSTimePtr pTimeout, pointer pReadmask) +{ +} + +static Bool LinuxApmRunning; + +static void LinuxApmWakeup(pointer blockData, int result, pointer pReadmask) +{ + fd_set *readmask = (fd_set *) pReadmask; + + if (result > 0 && LinuxApmFd >= 0 && FD_ISSET(LinuxApmFd, readmask)) { + apm_event_t event; + Bool running = LinuxApmRunning; + int cmd = APM_IOC_SUSPEND; + + while (read(LinuxApmFd, &event, sizeof(event)) == sizeof(event)) { + switch (event) { + case APM_SYS_STANDBY: + case APM_USER_STANDBY: + running = FALSE; + cmd = APM_IOC_STANDBY; + break; + case APM_SYS_SUSPEND: + case APM_USER_SUSPEND: + case APM_CRITICAL_SUSPEND: + running = FALSE; + cmd = APM_IOC_SUSPEND; + break; + case APM_NORMAL_RESUME: + case APM_CRITICAL_RESUME: + case APM_STANDBY_RESUME: + running = TRUE; + break; + } + } + if (running && !LinuxApmRunning) { + KdResume(); + LinuxApmRunning = TRUE; + } else if (!running && LinuxApmRunning) { + KdSuspend(); + LinuxApmRunning = FALSE; + ioctl(LinuxApmFd, cmd, 0); + } + } +} + +#ifdef FNONBLOCK +#define NOBLOCK FNONBLOCK +#else +#define NOBLOCK FNDELAY +#endif + +static void LinuxEnable(void) +{ + if (enabled) + return; + if (kdSwitchPending) { + kdSwitchPending = FALSE; + ioctl(LinuxConsoleFd, VT_RELDISP, VT_ACKACQ); + } + /* + * Open the APM driver + */ + LinuxApmFd = open("/dev/apm_bios", 2); + if (LinuxApmFd < 0 && errno == ENOENT) + LinuxApmFd = open("/dev/misc/apm_bios", 2); + if (LinuxApmFd >= 0) { + LinuxApmRunning = TRUE; + fcntl(LinuxApmFd, F_SETFL, + fcntl(LinuxApmFd, F_GETFL) | NOBLOCK); + RegisterBlockAndWakeupHandlers(LinuxApmBlock, LinuxApmWakeup, + 0); + AddEnabledDevice(LinuxApmFd); + } + + /* + * now get the VT + */ + LinuxSetSwitchMode(VT_AUTO); + if (ioctl(LinuxConsoleFd, VT_ACTIVATE, vtno) != 0) { + FatalError("LinuxInit: VT_ACTIVATE failed\n"); + } + if (ioctl(LinuxConsoleFd, VT_WAITACTIVE, vtno) != 0) { + FatalError("LinuxInit: VT_WAITACTIVE failed\n"); + } + LinuxSetSwitchMode(VT_PROCESS); + if (ioctl(LinuxConsoleFd, KDSETMODE, KD_GRAPHICS) < 0) { + FatalError("LinuxInit: KDSETMODE KD_GRAPHICS failed\n"); + } + enabled = TRUE; +} + +static Bool LinuxSpecialKey(KeySym sym) +{ + struct vt_stat vts; + int con; + + if (XK_F1 <= sym && sym <= XK_F12) { + con = sym - XK_F1 + 1; + memset(&vts, '\0', sizeof(vts)); /* valgrind */ + ioctl(LinuxConsoleFd, VT_GETSTATE, &vts); + if (con != vts.v_active && (vts.v_state & (1 << con))) { + ioctl(LinuxConsoleFd, VT_ACTIVATE, con); + return TRUE; + } + } + return FALSE; +} + +static void LinuxDisable(void) +{ + ioctl(LinuxConsoleFd, KDSETMODE, KD_TEXT); /* Back to text mode ... */ + if (kdSwitchPending) { + kdSwitchPending = FALSE; + ioctl(LinuxConsoleFd, VT_RELDISP, 1); + } + enabled = FALSE; + if (LinuxApmFd >= 0) { + RemoveBlockAndWakeupHandlers(LinuxApmBlock, LinuxApmWakeup, 0); + RemoveEnabledDevice(LinuxApmFd); + close(LinuxApmFd); + LinuxApmFd = -1; + } +} + +static void LinuxFini(void) +{ + struct vt_mode VT; + struct vt_stat vts; + int fd; + + if (LinuxConsoleFd < 0) + return; + + if (ioctl(LinuxConsoleFd, VT_GETMODE, &VT) != -1) { + VT.mode = VT_AUTO; + ioctl(LinuxConsoleFd, VT_SETMODE, &VT); /* set dflt vt handling */ + } + memset(&vts, '\0', sizeof(vts)); /* valgrind */ + ioctl(LinuxConsoleFd, VT_GETSTATE, &vts); + if (vtno == vts.v_active) { + /* + * Find a legal VT to switch to, either the one we started from + * or the lowest active one that isn't ours + */ + if (activeVT < 0 || + activeVT == vts.v_active || + !(vts.v_state & (1 << activeVT))) { + for (activeVT = 1; activeVT < 16; activeVT++) + if (activeVT != vtno + && (vts.v_state & (1 << activeVT))) + break; + if (activeVT == 16) + activeVT = -1; + } + /* + * Perform a switch back to the active VT when we were started + */ + if (activeVT >= -1) { + ioctl(LinuxConsoleFd, VT_ACTIVATE, activeVT); + ioctl(LinuxConsoleFd, VT_WAITACTIVE, activeVT); + activeVT = -1; + } + } + close(LinuxConsoleFd); /* make the vt-manager happy */ + fd = open("/dev/tty0", O_RDWR | O_NDELAY, 0); + if (fd >= 0) { + memset(&vts, '\0', sizeof(vts)); /* valgrind */ + ioctl(fd, VT_GETSTATE, &vts); + if (ioctl(fd, VT_DISALLOCATE, vtno) < 0) + fprintf(stderr, + "Can't deallocate console %d errno %d\n", vtno, + errno); + close(fd); + } + return; +} + +static const KdOsFuncs LinuxFuncs = { + LinuxInit, + LinuxEnable, + LinuxSpecialKey, + LinuxDisable, + LinuxFini, + 0 +}; + +void OsVendorInit(void) +{ + KdOsInit(&LinuxFuncs); +} diff --git a/kdrive/linux/mouse.c b/kdrive/linux/mouse.c new file mode 100644 index 0000000..459f668 --- /dev/null +++ b/kdrive/linux/mouse.c @@ -0,0 +1,943 @@ +/* + * + * Copyright © 2001 Keith Packard + * + * 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, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD 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_CONFIG_H +#include +#endif +#include +#include +#include +#include +#include +#include "inputstr.h" +#include "scrnintstr.h" +#include "kdrive.h" + +#undef DEBUG +#undef DEBUG_BYTES +#define KBUFIO_SIZE 256 +#define MOUSE_TIMEOUT 100 + +typedef struct _kbufio { + int fd; + unsigned char buf[KBUFIO_SIZE]; + int avail; + int used; +} Kbufio; + +static Bool MouseWaitForReadable(int fd, int timeout) +{ + fd_set set; + struct timeval tv, *tp; + int n; + CARD32 done; + + done = GetTimeInMillis() + timeout; + for (;;) { + FD_ZERO(&set); + FD_SET(fd, &set); + if (timeout == -1) + tp = 0; + else { + tv.tv_sec = timeout / 1000; + tv.tv_usec = (timeout % 1000) * 1000; + tp = &tv; + } + n = select(fd + 1, &set, 0, 0, tp); + if (n > 0) + return TRUE; + if (n < 0 && (errno == EAGAIN || errno == EINTR)) { + timeout = (int)(done - GetTimeInMillis()); + if (timeout > 0) + continue; + } + break; + } + return FALSE; +} + +static int MouseReadByte(Kbufio * b, int timeout) +{ + int n; + if (b->avail <= b->used) { + if (timeout && !MouseWaitForReadable(b->fd, timeout)) { +#ifdef DEBUG_BYTES + ErrorF("\tTimeout %d\n", timeout); +#endif + return -1; + } + n = read(b->fd, b->buf, KBUFIO_SIZE); + if (n <= 0) + return -1; + b->avail = n; + b->used = 0; + } +#ifdef DEBUG_BYTES + ErrorF("\tget %02x\n", b->buf[b->used]); +#endif + return b->buf[b->used++]; +} + +#if NOTUSED +static int MouseFlush(Kbufio * b, char *buf, int size) +{ + CARD32 now = GetTimeInMillis(); + CARD32 done = now + 100; + int c; + int n = 0; + + while ((c = MouseReadByte(b, done - now)) != -1) { + if (buf) { + if (n == size) { + memmove(buf, buf + 1, size - 1); + n--; + } + buf[n++] = c; + } + now = GetTimeInMillis(); + if ((INT32) (now - done) >= 0) + break; + } + return n; +} + +static int MousePeekByte(Kbufio * b, int timeout) +{ + int c; + + c = MouseReadByte(b, timeout); + if (c != -1) + --b->used; + return c; +} +#endif /* NOTUSED */ + +static Bool MouseWaitForWritable(int fd, int timeout) +{ + fd_set set; + struct timeval tv, *tp; + int n; + + FD_ZERO(&set); + FD_SET(fd, &set); + if (timeout == -1) + tp = 0; + else { + tv.tv_sec = timeout / 1000; + tv.tv_usec = (timeout % 1000) * 1000; + tp = &tv; + } + n = select(fd + 1, 0, &set, 0, tp); + if (n > 0) + return TRUE; + return FALSE; +} + +static Bool MouseWriteByte(const int fd, const unsigned char c, const int timeout) +{ + int ret; + +#ifdef DEBUG_BYTES + ErrorF("\tput %02x\n", c); +#endif + for (;;) { + ret = write(fd, &c, 1); + if (ret == 1) + return TRUE; + if (ret == 0) + return FALSE; + if (errno != EWOULDBLOCK) + return FALSE; + if (!MouseWaitForWritable(fd, timeout)) + return FALSE; + } +} + +static Bool MouseWriteBytes(const int fd, const unsigned char *c, int n, + const int timeout) +{ + while (n--) + if (!MouseWriteByte(fd, *c++, timeout)) + return FALSE; + return TRUE; +} + +#define MAX_MOUSE 10 /* maximum length of mouse protocol */ +#define MAX_SKIP 16 /* number of error bytes before switching */ +#define MAX_VALID 4 /* number of valid packets before accepting */ + +typedef struct _kmouseProt { + char *name; + Bool(*Complete) (KdMouseInfo * mi, unsigned char *ev, int ne); + int (*Valid) (KdMouseInfo * mi, unsigned char *ev, int ne); + Bool(*Parse) (KdMouseInfo * mi, unsigned char *ev, int ne); + Bool(*Init) (KdMouseInfo * mi); + unsigned char headerMask, headerValid; + unsigned char dataMask, dataValid; + Bool tty; + unsigned int c_iflag; + unsigned int c_oflag; + unsigned int c_lflag; + unsigned int c_cflag; + unsigned int speed; + unsigned char *init; + unsigned long state; +} KmouseProt; + +typedef enum _kmouseStage { + MouseBroken, MouseTesting, MouseWorking +} KmouseStage; + +typedef struct _kmouse { + Kbufio iob; + const KmouseProt *prot; + int i_prot; + KmouseStage stage; /* protocol verification stage */ + Bool tty; /* mouse device is a tty */ + int valid; /* sequential valid events */ + int tested; /* bytes scanned during Testing phase */ + int invalid; /* total invalid bytes for this protocol */ + unsigned long state; /* private per protocol, init to prot->state */ +} Kmouse; + +static int mouseValid(KdMouseInfo * mi, unsigned char *ev, int ne) +{ + Kmouse *km = mi->driver; + const KmouseProt *prot = km->prot; + int i; + + for (i = 0; i < ne; i++) + if ((ev[i] & prot->headerMask) == prot->headerValid) + break; + if (i != 0) + return i; + for (i = 1; i < ne; i++) + if ((ev[i] & prot->dataMask) != prot->dataValid) + return -1; + return 0; +} + +static Bool threeComplete(KdMouseInfo * mi, unsigned char *ev, int ne) +{ + return ne == 3; +} + +static Bool fourComplete(KdMouseInfo * mi, unsigned char *ev, int ne) +{ + return ne == 4; +} + +static Bool fiveComplete(KdMouseInfo * mi, unsigned char *ev, int ne) +{ + return ne == 5; +} + +static Bool MouseReasonable(KdMouseInfo * mi, unsigned long flags, int dx, + int dy) +{ + Kmouse *km = mi->driver; + + if (km->stage == MouseWorking) + return TRUE; + if (dx < -50 || dx > 50) { +#ifdef DEBUG + ErrorF("Large X %d\n", dx); +#endif + return FALSE; + } + if (dy < -50 || dy > 50) { +#ifdef DEBUG + ErrorF("Large Y %d\n", dy); +#endif + return FALSE; + } + return TRUE; +} + +/* + * Standard PS/2 mouse protocol + */ +static Bool ps2Parse(KdMouseInfo * mi, unsigned char *ev, int ne) +{ + Kmouse *km = mi->driver; + int dx, dy, dz; + unsigned long flags; + unsigned long flagsrelease = 0; + + flags = KD_MOUSE_DELTA; + if (ev[0] & 4) + flags |= KD_BUTTON_2; + if (ev[0] & 2) + flags |= KD_BUTTON_3; + if (ev[0] & 1) + flags |= KD_BUTTON_1; + + if (ne > 3) { + dz = (int)(signed char)ev[3]; + if (dz < 0) { + flags |= KD_BUTTON_4; + flagsrelease = KD_BUTTON_4; + } else if (dz > 0) { + flags |= KD_BUTTON_5; + flagsrelease = KD_BUTTON_5; + } + } + + dx = ev[1]; + if (ev[0] & 0x10) + dx -= 256; + dy = ev[2]; + if (ev[0] & 0x20) + dy -= 256; + dy = -dy; + if (!MouseReasonable(mi, flags, dx, dy)) + return FALSE; + if (km->stage == MouseWorking) { + KdEnqueueMouseEvent(mi, flags, dx, dy); + if (flagsrelease) { + flags &= ~flagsrelease; + KdEnqueueMouseEvent(mi, flags, dx, dy); + } + } + return TRUE; +} + +static Bool ps2Init(KdMouseInfo * mi); + +static const KmouseProt ps2Prot = { + "ps/2", + threeComplete, mouseValid, ps2Parse, ps2Init, + 0x08, 0x08, 0x00, 0x00, + FALSE +}; + +static const KmouseProt imps2Prot = { + "imps/2", + fourComplete, mouseValid, ps2Parse, ps2Init, + 0x08, 0x08, 0x00, 0x00, + FALSE +}; + +static const KmouseProt exps2Prot = { + "exps/2", + fourComplete, mouseValid, ps2Parse, ps2Init, + 0x08, 0x08, 0x00, 0x00, + FALSE +}; + +/* + * Once the mouse is known to speak ps/2 protocol, go and find out + * what advanced capabilities it has and turn them on + */ + +/* these extracted from FreeBSD 4.3 sys/dev/kbd/atkbdcreg.h */ + +/* aux device commands (sent to KBD_DATA_PORT) */ +#define PSMC_SET_SCALING11 0x00e6 +#define PSMC_SET_SCALING21 0x00e7 +#define PSMC_SET_RESOLUTION 0x00e8 +#define PSMC_SEND_DEV_STATUS 0x00e9 +#define PSMC_SET_STREAM_MODE 0x00ea +#define PSMC_SEND_DEV_DATA 0x00eb +#define PSMC_SET_REMOTE_MODE 0x00f0 +#define PSMC_SEND_DEV_ID 0x00f2 +#define PSMC_SET_SAMPLING_RATE 0x00f3 +#define PSMC_ENABLE_DEV 0x00f4 +#define PSMC_DISABLE_DEV 0x00f5 +#define PSMC_SET_DEFAULTS 0x00f6 +#define PSMC_RESET_DEV 0x00ff + +/* PSMC_SET_RESOLUTION argument */ +#define PSMD_RES_LOW 0 /* typically 25ppi */ +#define PSMD_RES_MEDIUM_LOW 1 /* typically 50ppi */ +#define PSMD_RES_MEDIUM_HIGH 2 /* typically 100ppi (default) */ +#define PSMD_RES_HIGH 3 /* typically 200ppi */ +#define PSMD_MAX_RESOLUTION PSMD_RES_HIGH + +/* PSMC_SET_SAMPLING_RATE */ +#define PSMD_MAX_RATE 255 /* FIXME: not sure if it's possible */ + +/* aux device ID */ +#define PSM_MOUSE_ID 0 +#define PSM_BALLPOINT_ID 2 +#define PSM_INTELLI_ID 3 +#define PSM_EXPLORER_ID 4 +#define PSM_4DMOUSE_ID 6 +#define PSM_4DPLUS_ID 8 + +static const unsigned char ps2_init[] = { + PSMC_ENABLE_DEV, + 0, +}; + +#define NINIT_PS2 1 + +static const unsigned char wheel_3button_init[] = { + PSMC_SET_SAMPLING_RATE, 200, + PSMC_SET_SAMPLING_RATE, 100, + PSMC_SET_SAMPLING_RATE, 80, + PSMC_SEND_DEV_ID, + 0, +}; + +#define NINIT_IMPS2 4 + +static const unsigned char wheel_5button_init[] = { + PSMC_SET_SAMPLING_RATE, 200, + PSMC_SET_SAMPLING_RATE, 100, + PSMC_SET_SAMPLING_RATE, 80, + PSMC_SET_SAMPLING_RATE, 200, + PSMC_SET_SAMPLING_RATE, 200, + PSMC_SET_SAMPLING_RATE, 80, + PSMC_SEND_DEV_ID, + 0 +}; + +#define NINIT_EXPS2 7 + +static const unsigned char intelli_init[] = { + PSMC_SET_SAMPLING_RATE, 200, + PSMC_SET_SAMPLING_RATE, 100, + PSMC_SET_SAMPLING_RATE, 80, + 0 +}; + +#define NINIT_INTELLI 3 + +static int ps2SkipInit(KdMouseInfo * mi, int ninit, Bool ret_next) +{ + Kmouse *km = mi->driver; + int c = -1; + Bool waiting; + + waiting = FALSE; + while (ninit || ret_next) { + c = MouseReadByte(&km->iob, MOUSE_TIMEOUT); + if (c == -1) + break; + /* look for ACK */ + if (c == 0xfa) { + ninit--; + if (ret_next) + waiting = TRUE; + } + /* look for packet start -- not the response */ + else if ((c & 0x08) == 0x08) + waiting = FALSE; + else if (waiting) + break; + } + return c; +} + +static Bool ps2Init(KdMouseInfo * mi) +{ + Kmouse *km = mi->driver; + int id; + const unsigned char *init; + int ninit; + + /* Send Intellimouse initialization sequence */ + MouseWriteBytes(km->iob.fd, intelli_init, strlen((char *)intelli_init), + 100); + /* + * Send ID command + */ + if (!MouseWriteByte(km->iob.fd, PSMC_SEND_DEV_ID, 100)) + return FALSE; + id = ps2SkipInit(mi, 0, TRUE); + switch (id) { + case 3: + init = wheel_3button_init; + ninit = NINIT_IMPS2; + km->prot = &imps2Prot; + break; + case 4: + init = wheel_5button_init; + ninit = NINIT_EXPS2; + km->prot = &exps2Prot; + break; + default: + init = ps2_init; + ninit = NINIT_PS2; + km->prot = &ps2Prot; + break; + } + if (init) + MouseWriteBytes(km->iob.fd, init, strlen((char *)init), 100); + /* + * Flush out the available data to eliminate responses to the + * initialization string. Make sure any partial event is + * skipped + */ + (void)ps2SkipInit(mi, ninit, FALSE); + return TRUE; +} + +static Bool busParse(KdMouseInfo * mi, unsigned char *ev, int ne) +{ + Kmouse *km = mi->driver; + int dx, dy; + unsigned long flags; + + flags = KD_MOUSE_DELTA; + dx = (signed char)ev[1]; + dy = -(signed char)ev[2]; + if ((ev[0] & 4) == 0) + flags |= KD_BUTTON_1; + if ((ev[0] & 2) == 0) + flags |= KD_BUTTON_2; + if ((ev[0] & 1) == 0) + flags |= KD_BUTTON_3; + if (!MouseReasonable(mi, flags, dx, dy)) + return FALSE; + if (km->stage == MouseWorking) + KdEnqueueMouseEvent(mi, flags, dx, dy); + return TRUE; +} + +static const KmouseProt busProt = { + "bus", + threeComplete, mouseValid, busParse, 0, + 0xf8, 0x00, 0x00, 0x00, + FALSE +}; + +/* + * Standard MS serial protocol, three bytes + */ + +static Bool msParse(KdMouseInfo * mi, unsigned char *ev, int ne) +{ + Kmouse *km = mi->driver; + int dx, dy; + unsigned long flags; + + flags = KD_MOUSE_DELTA; + + if (ev[0] & 0x20) + flags |= KD_BUTTON_1; + if (ev[0] & 0x10) + flags |= KD_BUTTON_3; + + dx = (signed char)(((ev[0] & 0x03) << 6) | (ev[1] & 0x3F)); + dy = (signed char)(((ev[0] & 0x0C) << 4) | (ev[2] & 0x3F)); + if (!MouseReasonable(mi, flags, dx, dy)) + return FALSE; + if (km->stage == MouseWorking) + KdEnqueueMouseEvent(mi, flags, dx, dy); + return TRUE; +} + +static const KmouseProt msProt = { + "ms", + threeComplete, mouseValid, msParse, 0, + 0xc0, 0x40, 0xc0, 0x00, + TRUE, + IGNPAR, + 0, + 0, + CS7 | CSTOPB | CREAD | CLOCAL, + B1200, +}; + +/* + * Logitech mice send 3 or 4 bytes, the only way to tell is to look at the + * first byte of a synchronized protocol stream and see if it's got + * any bits turned on that can't occur in that fourth byte + */ +static Bool logiComplete(KdMouseInfo * mi, unsigned char *ev, int ne) +{ + Kmouse *km = mi->driver; + + if ((ev[0] & 0x40) == 0x40) + return ne == 3; + if (km->stage != MouseBroken && (ev[0] & ~0x23) == 0) + return ne == 1; + return FALSE; +} + +static int logiValid(KdMouseInfo * mi, unsigned char *ev, int ne) +{ + Kmouse *km = mi->driver; + const KmouseProt *prot = km->prot; + int i; + + for (i = 0; i < ne; i++) { + if ((ev[i] & 0x40) == 0x40) + break; + if (km->stage != MouseBroken && (ev[i] & ~0x23) == 0) + break; + } + if (i != 0) + return i; + for (i = 1; i < ne; i++) + if ((ev[i] & prot->dataMask) != prot->dataValid) + return -1; + return 0; +} + +static Bool logiParse(KdMouseInfo * mi, unsigned char *ev, int ne) +{ + Kmouse *km = mi->driver; + int dx, dy; + unsigned long flags; + + flags = KD_MOUSE_DELTA; + + if (ne == 3) { + if (ev[0] & 0x20) + flags |= KD_BUTTON_1; + if (ev[0] & 0x10) + flags |= KD_BUTTON_3; + + dx = (signed char)(((ev[0] & 0x03) << 6) | (ev[1] & 0x3F)); + dy = (signed char)(((ev[0] & 0x0C) << 4) | (ev[2] & 0x3F)); + flags |= km->state & KD_BUTTON_2; + } else { + if (ev[0] & 0x20) + flags |= KD_BUTTON_2; + dx = 0; + dy = 0; + flags |= km->state & (KD_BUTTON_1 | KD_BUTTON_3); + } + + if (!MouseReasonable(mi, flags, dx, dy)) + return FALSE; + if (km->stage == MouseWorking) + KdEnqueueMouseEvent(mi, flags, dx, dy); + return TRUE; +} + +static const KmouseProt logiProt = { + "logitech", + logiComplete, logiValid, logiParse, 0, + 0xc0, 0x40, 0xc0, 0x00, + TRUE, + IGNPAR, + 0, + 0, + CS7 | CSTOPB | CREAD | CLOCAL, + B1200, +}; + +/* + * Mouse systems protocol, 5 bytes + */ +static Bool mscParse(KdMouseInfo * mi, unsigned char *ev, int ne) +{ + Kmouse *km = mi->driver; + int dx, dy; + unsigned long flags; + + flags = KD_MOUSE_DELTA; + + if (!(ev[0] & 0x4)) + flags |= KD_BUTTON_1; + if (!(ev[0] & 0x2)) + flags |= KD_BUTTON_2; + if (!(ev[0] & 0x1)) + flags |= KD_BUTTON_3; + dx = (signed char)(ev[1]) + (signed char)(ev[3]); + dy = -((signed char)(ev[2]) + (signed char)(ev[4])); + + if (!MouseReasonable(mi, flags, dx, dy)) + return FALSE; + if (km->stage == MouseWorking) + KdEnqueueMouseEvent(mi, flags, dx, dy); + return TRUE; +} + +static const KmouseProt mscProt = { + "msc", + fiveComplete, mouseValid, mscParse, 0, + 0xf8, 0x80, 0x00, 0x00, + TRUE, + IGNPAR, + 0, + 0, + CS8 | CSTOPB | CREAD | CLOCAL, + B1200, +}; + +/* + * Use logitech before ms -- they're the same except that + * logitech sometimes has a fourth byte + */ +static const KmouseProt *kmouseProts[] = { + &ps2Prot, &imps2Prot, &exps2Prot, &busProt, &logiProt, &msProt, + &mscProt, +}; + +#define NUM_PROT (sizeof (kmouseProts) / sizeof (kmouseProts[0])) + +static void MouseInitProtocol(Kmouse * km) +{ + int ret; + struct termios t; + + if (km->prot->tty) { + ret = tcgetattr(km->iob.fd, &t); + + if (ret >= 0) { + t.c_iflag = km->prot->c_iflag; + t.c_oflag = km->prot->c_oflag; + t.c_lflag = km->prot->c_lflag; + t.c_cflag = km->prot->c_cflag; + cfsetispeed(&t, km->prot->speed); + cfsetospeed(&t, km->prot->speed); + tcsetattr(km->iob.fd, TCSANOW, &t); + } + } + km->stage = MouseBroken; + km->valid = 0; + km->tested = 0; + km->invalid = 0; + km->state = km->prot->state; +} + +static void MouseFirstProtocol(Kmouse * km, char *prot) +{ + if (prot) { + for (km->i_prot = 0; km->i_prot < NUM_PROT; km->i_prot++) + if (!strcmp(prot, kmouseProts[km->i_prot]->name)) + break; + if (km->i_prot == NUM_PROT) { + int i; + ErrorF("Unknown mouse protocol \"%s\". Pick one of:", + prot); + for (i = 0; i < NUM_PROT; i++) + ErrorF(" %s", kmouseProts[i]->name); + ErrorF("\n"); + } else { + km->prot = kmouseProts[km->i_prot]; + if (km->tty && !km->prot->tty) + ErrorF + ("Mouse device is serial port, protocol %s is not serial protocol\n", + prot); + else if (!km->tty && km->prot->tty) + ErrorF + ("Mouse device is not serial port, protocol %s is serial protocol\n", + prot); + } + } + if (!km->prot) { + for (km->i_prot = 0; kmouseProts[km->i_prot]->tty != km->tty; + km->i_prot++) ; + km->prot = kmouseProts[km->i_prot]; + } + MouseInitProtocol(km); +} + +static void MouseNextProtocol(Kmouse * km) +{ + do { + if (!km->prot) + km->i_prot = 0; + else if (++km->i_prot == NUM_PROT) + km->i_prot = 0; + km->prot = kmouseProts[km->i_prot]; + } while (km->prot->tty != km->tty); + MouseInitProtocol(km); + ErrorF("Switching to mouse protocol \"%s\"\n", km->prot->name); +} + +static void MouseRead(int mousePort, void *closure) +{ + KdMouseInfo *mi = closure; + Kmouse *km = mi->driver; + unsigned char event[MAX_MOUSE]; + int ne; + int c; + int i; + int timeout; + + timeout = 0; + ne = 0; + for (;;) { + c = MouseReadByte(&km->iob, timeout); + if (c == -1) { + if (ne) { + km->invalid += ne + km->tested; + km->valid = 0; + km->tested = 0; + km->stage = MouseBroken; + } + break; + } + event[ne++] = c; + i = (*km->prot->Valid) (mi, event, ne); + if (i != 0) { +#ifdef DEBUG + ErrorF("Mouse protocol %s broken %d of %d bytes bad\n", + km->prot->name, i > 0 ? i : ne, ne); +#endif + if (i > 0 && i < ne) { + ne -= i; + memmove(event, event + i, ne); + } else { + i = ne; + ne = 0; + } + km->invalid += i + km->tested; + km->valid = 0; + km->tested = 0; + if (km->stage == MouseWorking) + km->i_prot--; + km->stage = MouseBroken; + if (km->invalid > MAX_SKIP) { + MouseNextProtocol(km); + ne = 0; + } + timeout = 0; + } else { + if ((*km->prot->Complete) (mi, event, ne)) { + if ((*km->prot->Parse) (mi, event, ne)) { + switch (km->stage) { + case MouseBroken: +#ifdef DEBUG + ErrorF + ("Mouse protocol %s seems OK\n", + km->prot->name); +#endif + /* do not zero invalid to accumulate invalid bytes */ + km->valid = 0; + km->tested = 0; + km->stage = MouseTesting; + /* fall through ... */ + case MouseTesting: + km->valid++; + km->tested += ne; + if (km->valid > MAX_VALID) { +#ifdef DEBUG + ErrorF + ("Mouse protocol %s working\n", + km->prot->name); +#endif + km->stage = + MouseWorking; + km->invalid = 0; + km->tested = 0; + km->valid = 0; + if (km->prot->Init + && !(*km->prot-> + Init) (mi)) + km->stage = + MouseBroken; + } + break; + case MouseWorking: + break; + } + } else { + km->invalid += ne + km->tested; + km->valid = 0; + km->tested = 0; + km->stage = MouseBroken; + } + ne = 0; + timeout = 0; + } else + timeout = MOUSE_TIMEOUT; + } + } +} + +static int MouseInputType; + +const char * const kdefaultMouse[] = { + "/dev/mouse", + "/dev/psaux", + "/dev/input/mice", + "/dev/adbmouse", + "/dev/ttyS0", + "/dev/ttyS1", +}; + +#define NUM_DEFAULT_MOUSE (sizeof (kdefaultMouse) / sizeof (kdefaultMouse[0])) + +static Bool MouseInit(void) +{ + int i; + int fd = -1; + Kmouse *km; + KdMouseInfo *mi, *next; + int n = 0; + + if (!MouseInputType) + MouseInputType = KdAllocInputType(); + + for (mi = kdMouseInfo; mi; mi = next) { + next = mi->next; + if (mi->inputType) + continue; + if (!mi->name) { + for (i = 0; i < NUM_DEFAULT_MOUSE; i++) { + fd = open(kdefaultMouse[i], 2); + if (fd >= 0) { + mi->name = strdup(kdefaultMouse[i]); + break; + } + } + } else + fd = open(mi->name, 2); + + if (fd >= 0) { + km = malloc(sizeof(Kmouse)); + if (km) { + km->iob.fd = fd; + km->iob.avail = km->iob.used = 0; + km->prot = 0; + km->i_prot = 0; + km->tty = isatty(fd); + mi->driver = km; + mi->inputType = MouseInputType; + MouseFirstProtocol(km, mi->prot); + if (KdRegisterFd + (MouseInputType, fd, MouseRead, (void *)mi)) + n++; + } else + close(fd); + } + } + return TRUE; +} + +static void MouseFini(void) +{ + KdMouseInfo *mi; + + KdUnregisterFds(MouseInputType, TRUE); + for (mi = kdMouseInfo; mi; mi = mi->next) { + if (mi->inputType == MouseInputType) { + free(mi->driver); + mi->driver = 0; + mi->inputType = 0; + } + } +} + +const KdMouseFuncs LinuxMouseFuncs = { + MouseInit, + MouseFini, +}; diff --git a/kdrive/src/Makefile.am b/kdrive/src/Makefile.am new file mode 100644 index 0000000..8c0ac65 --- /dev/null +++ b/kdrive/src/Makefile.am @@ -0,0 +1,22 @@ +AM_CPPFLAGS = \ + @KDRIVE_INCS@ \ + @KDRIVE_CFLAGS@ + +AM_CFLAGS = -DHAVE_DIX_CONFIG_H + +noinst_LIBRARIES = libkdrive.a libkdrivestubs.a + +libkdrive_a_SOURCES = \ + kcmap.c \ + kdrive.c \ + kdrive.h \ + kinfo.c \ + kinput.c \ + kkeymap.h \ + kmap.c \ + kmode.c \ + kshadow.c \ + $(top_srcdir)/mi/miinitext.c + +libkdrivestubs_a_SOURCES = \ + $(top_srcdir)/fb/fbcmap.c diff --git a/kdrive/src/kcmap.c b/kdrive/src/kcmap.c new file mode 100644 index 0000000..7fee5ff --- /dev/null +++ b/kdrive/src/kcmap.c @@ -0,0 +1,241 @@ +/* + * + * Copyright © 1999 Keith Packard + * + * 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, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD 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_CONFIG_H +#include +#endif +#include "kdrive.h" + +/* + * Put the entire colormap into the DAC + */ + +static void KdSetColormap(ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + ColormapPtr pCmap = pScreenPriv->pInstalledmap; + + Pixel pixels[KD_MAX_PSEUDO_SIZE]; + + xrgb colors[KD_MAX_PSEUDO_SIZE]; + + xColorItem defs[KD_MAX_PSEUDO_SIZE]; + + int i; + + if (!pScreenPriv->card->cfuncs->putColors) + return; + if (pScreenPriv->screen->fb.depth > KD_MAX_PSEUDO_DEPTH) + return; + + if (!pScreenPriv->enabled) + return; + + if (!pCmap) + return; + + /* + * Make DIX convert pixels into RGB values -- this handles + * true/direct as well as pseudo/static visuals + */ + + for (i = 0; i < (1 << pScreenPriv->screen->fb.depth); i++) + pixels[i] = i; + + QueryColors(pCmap, (1 << pScreenPriv->screen->fb.depth), pixels, + colors); + + for (i = 0; i < (1 << pScreenPriv->screen->fb.depth); i++) { + defs[i].pixel = i; + defs[i].red = colors[i].red; + defs[i].green = colors[i].green; + defs[i].blue = colors[i].blue; + defs[i].flags = DoRed | DoGreen | DoBlue; + } + + (*pScreenPriv->card->cfuncs->putColors) (pCmap->pScreen, + (1 << pScreenPriv->screen-> + fb.depth), defs); + + /* recolor hardware cursor */ + if (pScreenPriv->card->cfuncs->recolorCursor) + (*pScreenPriv->card->cfuncs->recolorCursor) (pCmap->pScreen, 0, + 0); +} + +/* + * When the hardware is enabled, save the hardware colors and store + * the current colormap + */ +void KdEnableColormap(ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + int i; + + if (!pScreenPriv->card->cfuncs->putColors) + return; + if (pScreenPriv->screen->fb.depth <= KD_MAX_PSEUDO_DEPTH) { + for (i = 0; i < (1 << pScreenPriv->screen->fb.depth); i++) + pScreenPriv->systemPalette[i].pixel = i; + (*pScreenPriv->card->cfuncs->getColors) (pScreen, + (1 << pScreenPriv-> + screen->fb.depth), + pScreenPriv-> + systemPalette); + } + KdSetColormap(pScreen); +} + +void KdDisableColormap(ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + + if (!pScreenPriv->card->cfuncs->putColors) + return; + if (pScreenPriv->screen->fb.depth <= KD_MAX_PSEUDO_DEPTH) { + (*pScreenPriv->card->cfuncs->putColors) (pScreen, + (1 << pScreenPriv-> + screen->fb.depth), + pScreenPriv-> + systemPalette); + } +} + +/* + * KdInstallColormap + * + * This function is called when the server receives a request to install a + * colormap or when the server needs to install one on its own, like when + * there's no window manager running and the user has moved the pointer over + * an X client window. It needs to build an identity Windows palette for the + * colormap and realize it into the Windows system palette. + */ +void KdInstallColormap(ColormapPtr pCmap) +{ + KdScreenPriv(pCmap->pScreen); + + if (pCmap == pScreenPriv->pInstalledmap) + return; + + /* Tell X clients that the installed colormap is going away. */ + if (pScreenPriv->pInstalledmap) + WalkTree(pScreenPriv->pInstalledmap->pScreen, TellLostMap, + (pointer) & (pScreenPriv->pInstalledmap->mid)); + + /* Take note of the new installed colorscreen-> */ + pScreenPriv->pInstalledmap = pCmap; + + KdSetColormap(pCmap->pScreen); + + /* Tell X clients of the new colormap */ + WalkTree(pCmap->pScreen, TellGainedMap, (pointer) & (pCmap->mid)); +} + +/* + * KdUninstallColormap + * + * This function uninstalls a colormap by either installing + * the default X colormap or erasing the installed colormap pointer. + * The default X colormap itself cannot be uninstalled. + */ +void KdUninstallColormap(ColormapPtr pCmap) +{ + KdScreenPriv(pCmap->pScreen); + Colormap defMapID; + ColormapPtr defMap; + + /* ignore if not installed */ + if (pCmap != pScreenPriv->pInstalledmap) + return; + + /* ignore attempts to uninstall default colormap */ + defMapID = pCmap->pScreen->defColormap; + if ((Colormap) pCmap->mid == defMapID) + return; + + /* install default */ + defMap = (ColormapPtr) LookupIDByType(defMapID, RT_COLORMAP); + if (defMap) + (*pCmap->pScreen->InstallColormap) (defMap); + else { + /* uninstall and clear colormap pointer */ + WalkTree(pCmap->pScreen, TellLostMap, (pointer) & (pCmap->mid)); + pScreenPriv->pInstalledmap = 0; + } +} + +int KdListInstalledColormaps(ScreenPtr pScreen, Colormap * pCmaps) +{ + KdScreenPriv(pScreen); + int n = 0; + + if (pScreenPriv->pInstalledmap) { + *pCmaps++ = pScreenPriv->pInstalledmap->mid; + n++; + } + return n; +} + +/* + * KdStoreColors + * + * This function is called whenever the server receives a request to store + * color values into one or more entries in the currently installed X + * colormap; it can be either the default colormap or a private colorscreen-> + */ +void KdStoreColors(ColormapPtr pCmap, int ndef, xColorItem * pdefs) +{ + KdScreenPriv(pCmap->pScreen); + VisualPtr pVisual; + xColorItem expanddefs[KD_MAX_PSEUDO_SIZE]; + + if (pCmap != pScreenPriv->pInstalledmap) + return; + + if (!pScreenPriv->card->cfuncs->putColors) + return; + + if (pScreenPriv->screen->fb.depth > KD_MAX_PSEUDO_DEPTH) + return; + + if (!pScreenPriv->enabled) + return; + + /* Check for DirectColor or TrueColor being simulated on a PseudoColor device. */ + pVisual = pCmap->pVisual; + if ((pVisual->class | DynamicClass) == DirectColor) { + /* + * Expand DirectColor or TrueColor color values into a PseudoColor + * format. Defer to the Color Framebuffer (CFB) code to do that. + */ + ndef = fbExpandDirectColors(pCmap, ndef, pdefs, expanddefs); + pdefs = expanddefs; + } + + (*pScreenPriv->card->cfuncs->putColors) (pCmap->pScreen, ndef, pdefs); + + /* recolor hardware cursor */ + if (pScreenPriv->card->cfuncs->recolorCursor) + (*pScreenPriv->card->cfuncs->recolorCursor) (pCmap->pScreen, + ndef, pdefs); +} diff --git a/kdrive/src/kdrive.c b/kdrive/src/kdrive.c new file mode 100644 index 0000000..49af570 --- /dev/null +++ b/kdrive/src/kdrive.c @@ -0,0 +1,1230 @@ +/* + * + * Copyright © 1999 Keith Packard + * + * 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, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD 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_CONFIG_H +#include +#endif +#include "kdrive.h" +#include +#include +#include +#include "micmap.h" + +#ifdef DPMSExtension +#include "dpmsproc.h" +#endif + +typedef struct _kdDepths { + CARD8 depth; + CARD8 bpp; +} KdDepths; + +static const KdDepths kdDepths[] = { + {1, 1}, + {4, 4}, + {8, 8}, + {15, 16}, + {16, 16}, + {24, 32}, + {32, 32} +}; + +#define NUM_KD_DEPTHS (sizeof (kdDepths) / sizeof (kdDepths[0])) + +int kdScreenPrivateIndex; + +static unsigned long kdGeneration; +static Bool kdEmulateMiddleButton; +static Bool kdRawPointerCoordinates; +Bool kdDisableZaphod; +Bool kdDontZap; +static Bool kdEnabled; +static int kdSubpixelOrder; +int kdVirtualTerminal = -1; +Bool kdSwitchPending; +static const char *kdSwitchCmd; +static DDXPointRec kdOrigin; + +/* + * Carry arguments from InitOutput through driver initialization + * to KdScreenInit + */ + +const KdOsFuncs *kdOsFuncs; + +static void KdSetRootClip(ScreenPtr pScreen, BOOL enable) +{ + WindowPtr pWin = WindowTable[pScreen->myNum]; + + WindowPtr pChild; + + Bool WasViewable; + + Bool anyMarked = FALSE; + + WindowPtr pLayerWin; + + BoxRec box; + + if (!pWin) + return; + WasViewable = (Bool) (pWin->viewable); + if (WasViewable) { + for (pChild = pWin->firstChild; pChild; + pChild = pChild->nextSib) { + (void)(*pScreen->MarkOverlappedWindows) (pChild, pChild, + &pLayerWin); + } + (*pScreen->MarkWindow) (pWin); + anyMarked = TRUE; + if (pWin->valdata) { + if (HasBorder(pWin)) { + RegionPtr borderVisible; + + borderVisible = + REGION_CREATE(NullBox, 1); + REGION_SUBTRACT(borderVisible, + &pWin->borderClip, + &pWin->winSize); + pWin->valdata->before.borderVisible = + borderVisible; + } + pWin->valdata->before.resized = TRUE; + } + } + + if (enable) { + box.x1 = 0; + box.y1 = 0; + box.x2 = pScreen->width; + box.y2 = pScreen->height; + + BoxRec *boxptr = &box; + + pWin->drawable.width = pScreen->width; + pWin->drawable.height = pScreen->height; + REGION_INIT(&pWin->winSize, boxptr, 1); + REGION_INIT(&pWin->borderSize, boxptr, 1); + REGION_RESET(&pWin->borderClip, &box); + REGION_BREAK(&pWin->clipList); + } else { + REGION_EMPTY(&pWin->borderClip); + REGION_BREAK(&pWin->clipList); + } + + ResizeChildrenWinSize(pWin, 0, 0, 0, 0); + + if (WasViewable) { + if (pWin->firstChild) { + anyMarked |= + (*pScreen->MarkOverlappedWindows) (pWin->firstChild, + pWin->firstChild, + (WindowPtr *) + NULL); + } else { + (*pScreen->MarkWindow) (pWin); + anyMarked = TRUE; + } + + + if (anyMarked) + (*pScreen->ValidateTree) (pWin, NullWindow, VTOther); + } + + if (WasViewable) { + if (anyMarked) + (*pScreen->HandleExposures) (pWin); + if (anyMarked && pScreen->PostValidateTree) + (*pScreen->PostValidateTree) (pWin, NullWindow, + VTOther); + } + if (pWin->realized) + WindowsRestructured(); +} + +void KdDisableScreen(ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + + if (!pScreenPriv->enabled) + return; + if (!pScreenPriv->closed) + KdSetRootClip(pScreen, FALSE); + KdDisableColormap(pScreen); + if (!pScreenPriv->screen->dumb + && pScreenPriv->card->cfuncs->disableAccel) + (*pScreenPriv->card->cfuncs->disableAccel) (pScreen); + if (!pScreenPriv->screen->softCursor && + pScreenPriv->card->cfuncs->disableCursor) + (*pScreenPriv->card->cfuncs->disableCursor) (pScreen); + if (pScreenPriv->card->cfuncs->dpms) + (*pScreenPriv->card->cfuncs->dpms) (pScreen, KD_DPMS_NORMAL); + pScreenPriv->enabled = FALSE; + if (pScreenPriv->card->cfuncs->disable) + (*pScreenPriv->card->cfuncs->disable) (pScreen); +} + +static void KdDoSwitchCmd(const char *const reason) +{ + if (kdSwitchCmd) { + char *command; + + if (asprintf(&command, "%s %s", kdSwitchCmd, reason) == -1) + return; + system(command); + free(command); + } +} + +void KdSuspend(void) +{ + KdCardInfo *card; + KdScreenInfo *screen; + + if (kdEnabled) { + for (card = kdCardInfo; card; card = card->next) { + for (screen = card->screenList; screen; + screen = screen->next) + if (screen->mynum == card->selected + && screen->pScreen) + KdDisableScreen(screen->pScreen); + if (card->driver && card->cfuncs->restore) + (*card->cfuncs->restore) (card); + } + KdDisableInput(); + KdDoSwitchCmd("suspend"); + } +} + +static void KdDisableScreens(void) +{ + KdSuspend(); + if (kdEnabled) { + if (kdOsFuncs->Disable) + (*kdOsFuncs->Disable) (); + kdEnabled = FALSE; + } +} + +Bool KdEnableScreen(ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + + if (pScreenPriv->enabled) + return TRUE; + if (pScreenPriv->card->cfuncs->enable) + if (!(*pScreenPriv->card->cfuncs->enable) (pScreen)) + return FALSE; + pScreenPriv->enabled = TRUE; + pScreenPriv->dpmsState = KD_DPMS_NORMAL; + pScreenPriv->card->selected = pScreenPriv->screen->mynum; + if (!pScreenPriv->screen->softCursor && + pScreenPriv->card->cfuncs->enableCursor) + (*pScreenPriv->card->cfuncs->enableCursor) (pScreen); + if (!pScreenPriv->screen->dumb + && pScreenPriv->card->cfuncs->enableAccel) + (*pScreenPriv->card->cfuncs->enableAccel) (pScreen); + KdEnableColormap(pScreen); + KdSetRootClip(pScreen, TRUE); + if (pScreenPriv->card->cfuncs->dpms) + (*pScreenPriv->card->cfuncs->dpms) (pScreen, + pScreenPriv->dpmsState); + return TRUE; +} + +void KdResume(void) +{ + KdCardInfo *card; + KdScreenInfo *screen; + + if (kdEnabled) { + KdDoSwitchCmd("resume"); + for (card = kdCardInfo; card; card = card->next) { + if (card->cfuncs->preserve) + (*card->cfuncs->preserve) (card); + for (screen = card->screenList; screen; + screen = screen->next) + if (screen->mynum == card->selected + && screen->pScreen) + KdEnableScreen(screen->pScreen); + } + KdEnableInput(); + KdReleaseAllKeys(); + } +} + +static void KdEnableScreens(void) +{ + if (!kdEnabled) { + kdEnabled = TRUE; + if (kdOsFuncs->Enable) + (*kdOsFuncs->Enable) (); + } + KdResume(); +} + +void KdProcessSwitch(void) +{ + if (kdEnabled) + KdDisableScreens(); + else + KdEnableScreens(); +} + +void AbortDDX(void) +{ + KdDisableScreens(); + if (kdOsFuncs) { + if (kdEnabled && kdOsFuncs->Disable) + (*kdOsFuncs->Disable) (); + if (kdOsFuncs->Fini) + (*kdOsFuncs->Fini) (); + KdDoSwitchCmd("stop"); + } +} + +void ddxGiveUp() +{ + AbortDDX(); +} + +static Bool kdDumbDriver; + +static Bool kdSoftCursor; + +static const char *KdParseFindNext(const char *cur, const char *delim, + char *save, char *last) +{ + while (*cur && !strchr(delim, *cur)) { + *save++ = *cur++; + } + *save = 0; + *last = *cur; + if (*cur) + cur++; + return cur; +} + +Rotation KdAddRotation(Rotation a, Rotation b) +{ + Rotation rotate = (a & RR_Rotate_All) * (b & RR_Rotate_All); + Rotation reflect = (a & RR_Reflect_All) ^ (b & RR_Reflect_All); + + if (rotate > RR_Rotate_270) + rotate /= (RR_Rotate_270 * RR_Rotate_90); + return reflect | rotate; +} + +Rotation KdSubRotation(Rotation a, Rotation b) +{ + Rotation rotate = (a & RR_Rotate_All) * 16 / (b & RR_Rotate_All); + Rotation reflect = (a & RR_Reflect_All) ^ (b & RR_Reflect_All); + + if (rotate > RR_Rotate_270) + rotate /= (RR_Rotate_270 * RR_Rotate_90); + return reflect | rotate; +} + +static void KdParseScreen(KdScreenInfo * screen, const char *arg) +{ + char delim; + char save[1024]; + int i; + int pixels, mm; + + screen->dumb = kdDumbDriver; + screen->softCursor = kdSoftCursor; + screen->origin = kdOrigin; + screen->randr = RR_Rotate_0; + screen->width = 0; + screen->height = 0; + screen->width_mm = 0; + screen->height_mm = 0; + screen->subpixel_order = kdSubpixelOrder; + screen->rate = 0; + screen->fb.depth = 0; + if (!arg) + return; + if (strlen(arg) >= sizeof(save)) + return; + + for (i = 0; i < 2; i++) { + arg = KdParseFindNext(arg, "x/@XY", save, &delim); + if (!save[0]) + return; + + pixels = atoi(save); + mm = 0; + + if (delim == '/') { + arg = KdParseFindNext(arg, "x@XY", save, &delim); + if (!save[0]) + return; + mm = atoi(save); + } + + if (i == 0) { + screen->width = pixels; + screen->width_mm = mm; + } else { + screen->height = pixels; + screen->height_mm = mm; + } + if (delim != 'x' && delim != '@' && delim != 'X' + && delim != 'Y') + return; + } + + kdOrigin.x += screen->width; + kdOrigin.y = 0; + kdDumbDriver = FALSE; + kdSoftCursor = FALSE; + kdSubpixelOrder = SubPixelUnknown; + + if (delim == '@') { + arg = KdParseFindNext(arg, "xXY", save, &delim); + if (save[0]) { + int rotate = atoi(save); + + if (rotate < 45) + screen->randr = RR_Rotate_0; + else if (rotate < 135) + screen->randr = RR_Rotate_90; + else if (rotate < 225) + screen->randr = RR_Rotate_180; + else if (rotate < 315) + screen->randr = RR_Rotate_270; + else + screen->randr = RR_Rotate_0; + } + } + if (delim == 'X') { + arg = KdParseFindNext(arg, "xY", save, &delim); + screen->randr |= RR_Reflect_X; + } + + if (delim == 'Y') { + arg = KdParseFindNext(arg, "xY", save, &delim); + screen->randr |= RR_Reflect_Y; + } + + arg = KdParseFindNext(arg, "x/,", save, &delim); + if (save[0]) { + screen->fb.depth = atoi(save); + if (delim == '/') { + arg = KdParseFindNext(arg, "x,", save, &delim); + if (save[0]) + screen->fb.bitsPerPixel = atoi(save); + } else + screen->fb.bitsPerPixel = 0; + } + + if (delim == 'x') { + KdParseFindNext(arg, "x", save, &delim); + if (save[0]) + screen->rate = atoi(save); + } +} + +/* + * Mouse argument syntax: + * + * device,protocol,options... + * + * Options are any of: + * 1-5 n button mouse + * 2button emulate middle button + * {NMO} Reorder buttons + */ + +/* + * Parse mouse information. Syntax: + * + * ,,{,