/* $Id: ps_replies.c,v 1.1.1.1 90/11/28 16:45:21 altenhof Exp $ */

/*
 * Copyright (C) 1990 by Digital Equipment Corporation.
 * 
 * Author: Michael P. Altenhofen, CEC Karlsruhe e-mail:
 * Altenhofen@kampus.enet.dec.com
 * 
 * This file ist part of Shared X
 * 
 * Permission to use, copy, modify, and distribute this software and its
 * documentation without fee is hereby granted, but only for non-profit  use
 * and distribution,  and provided  that the copyright notice and this notice
 * is preserved on all copies.
 * 
 * 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 <X11/Xatom.h>

#define PUBLIC extern

#define _USE_STRUCTS_		/* we use MUX specific data here */
#define _USE_PROTO_		/* we must include Xproto.h */

#define NEED_REPLIES		/* flag that we need x"..."Reply definitions
				 * from Xproto.h */
#define _XEVENT_		/* flag that we don't need XEvent definition
				 * here */
#include "glob.h"

#include "utils.h"
#include "events.h"
#include "resources.h"
#include "build.h"
#include "map.h"

#undef PUBLIC


#include <X11/Xutil.h>		/* used in case we show pixmaps */

#include "requestnames.h"	/* mapping req type --> req name */

/* -- some frequently used macros -- */

#define GETDISPLAY( dpy , client ) \
          if( ( dpy = XDisplay( client ) ) == NULL )\
          {\
              ErrorF( "Can't find display of client %d!\n" , \
                                 ClientConnection( client ) ) ; \
              return( BadValue ) ;\
          }


#define MAPID( res , id , map , from_where ) \
         if( ( res = MapID( id , map , from_where ) ) == InvalidID )\
          {\
              ErrorF( "Can't proceed (ID map failure)!\n " ) ;\
	      return( BadIDChoice ) ;\
	  }

  /*
   * Use a more descriptive name here:
   * Xlib fuctions that return a reply back to the client (and that we handle
   * here) queue up events that arrive during their wait for the server
   * reply. To guarantee the correct event/reply sequence we have to
   * "reserialize" the reply, i.e. queue up the intermediate events before we
   * send the reply back to the client; this is done by calling
   * HandleOneServer without flushing the output queue. OK?
   */

#define RESERIALIZE(dpy) HandleOneServer(dpy , NO_FLUSH)
#define NO_FLUSH 0


/* XXX -- no such macro in Xlib  */

#define VisualID(visual) (visual->visualid)

static Display *dpy;
static int get_image = TRUE;
static int format = ZPixmap;

int
_ProcGetWindowAttributes (client)
  ClientPtr client;
{
  register xResourceReq *req = (xResourceReq *) client->requestBuffer;
  xGetWindowAttributesReply reply;
  register XID win;
  XWindowAttributes attributes;
  register int idmap, ok;

  GETDISPLAY (dpy, client);
  idmap = ConnectionNumber (dpy);
  MAPID (win, req->id, idmap, FromClient);

  ok = XGetWindowAttributes (dpy, win, &attributes);

  /*
   * XGetWindowAttributes does GetWindowAttributes AND GetGeometry, but
   * our client will send us this GetGeometry as it's next request
   * -> "our" server will only be one serial more "ahead"
   */
  ServerAhead[idmap]++;


  /* ensure reply/event sequence */
  RESERIALIZE (dpy);

  if (ok) {
    reply.type = X_Reply;
    reply.length = (sizeof (xGetWindowAttributesReply) -
		    sizeof (xGenericReply)) >> 2;
    reply.backingStore = attributes.backing_store;
    reply.sequenceNumber = client->sequence;
    reply.class = attributes.class;
    reply.bitGravity = attributes.bit_gravity;
    reply.winGravity = attributes.win_gravity;
    reply.backingBitPlanes = attributes.backing_planes;
    reply.backingPixel = attributes.backing_pixel;
    reply.saveUnder = attributes.save_under;
    reply.mapInstalled = attributes.map_installed;
    reply.mapState = attributes.map_state;
    reply.override = attributes.override_redirect;
    reply.allEventMasks = attributes.all_event_masks;

    /*
     * X has possibly added event masks -> retrieve this information
     * from the event mask map
     */
    reply.yourEventMask =
      attributes.your_event_mask &
      ~GetEventExclusionMask (req->id,
			      ClientConnection (client));
    reply.doNotPropagateMask = attributes.do_not_propagate_mask;

    /*
     * the WindowAttributes structure contains ID's -> map them
     */
    reply.colormap = MapID (attributes.colormap, idmap, FromServer);
    reply.visualID = MapID (VisualID (attributes.visual), idmap,
			    FromServer);

    WriteToClient (client, sizeof (xGetWindowAttributesReply),
		   (char *) &reply);

    return (client->noClientException);
  }
  return (clientErrorValue ? clientErrorValue : BadAlloc);
}

int
_ProcGetGeometry (client)
  ClientPtr client;
{
  register xResourceReq *req = (xResourceReq *) client->requestBuffer;
  xGetGeometryReply reply;
  register XID drawable;
  XID root;
  register int idmap, ok;
  int x, y;
  unsigned int width, height, border_width, depth;

  GETDISPLAY (dpy, client);
  idmap = ConnectionNumber (dpy);
  MAPID (drawable, req->id, idmap, FromClient);

  ok = XGetGeometry (dpy, drawable,
		     &root, &x, &y, &width, &height,
		     &border_width, &depth);

  /* ensure reply/event sequence */
  RESERIALIZE (dpy);

  if (ok) {
    reply.type = X_Reply;
    reply.length = 0;
    reply.sequenceNumber = client->sequence;
    reply.width = width;
    reply.height = height;
    reply.borderWidth = border_width;
    reply.depth = depth;
    reply.x = x;
    reply.y = y;
    reply.root = MapID (root, idmap, FromServer);

    WriteToClient (client, sizeof (xGetGeometryReply),
		   (char *) &reply);

    return (client->noClientException);
  }
  return (clientErrorValue ? clientErrorValue : BadAccess);
}

int
_ProcQueryTree (client)		/* 15 */
  ClientPtr client;
{
  register xResourceReq *req = (xResourceReq *) client->requestBuffer;
  xQueryTreeReply reply;
  register XID window;
  XID root, parent, *children;
  int idmap, i;
  unsigned int num_children, ok;

  children = (XID *) NULL;

  GETDISPLAY (dpy, client);
  idmap = ConnectionNumber (dpy);
  MAPID (window, req->id, idmap, FromClient);

  ok = XQueryTree (dpy, window,
		   &root, &parent,
		   &children, &num_children);

  /* ensure reply/event sequence */
  RESERIALIZE (dpy);

  if (ok) {
    reply.type = X_Reply;
    reply.sequenceNumber = client->sequence;
    reply.length = num_children;
    reply.root = MapID (root, idmap, FromServer);
    reply.parent = MapID (parent, idmap, FromServer);
    reply.nChildren = num_children;

    for (i = 0; i < num_children; i++)
      children[i] = MapID (children[i], idmap, FromServer);

    WriteToClient (client, sizeof (xQueryTreeReply),
		   (char *) &reply);
    WriteToClient (client, num_children * sizeof (XID),
		   (char *) children);

    Xfree ((char *) children);

    return (client->noClientException);
  }
  else
    return (clientErrorValue ? clientErrorValue : BadAlloc);
}

int
_ProcInternAtom (client)
  ClientPtr client;
{
  register xInternAtomReq *req = (xInternAtomReq *) client->requestBuffer;
  xInternAtomReply reply;
  char *name = NULL;

  GETDISPLAY (dpy, client);
  if ((name = (char *) Xmalloc (req->nbytes + 1)) == NULL) {
    ErrorF ("Out of memory!\n");
    return (BadAlloc);
  }
  bcopy ((char *) &req[1], name, req->nbytes);
  name[req->nbytes] = '\0';
  reply.atom = XInternAtom (dpy, name, req->onlyIfExists);
  /* ensure reply/event sequence */
  RESERIALIZE (dpy);

  /*
   * There are two atoms of special interest: DEC_WM_HINTS and
   * DEC_WM_DECORATION_GEOMETRY.
   * We must check for these in (Change/Get)Property
   */
  if (!strcmp ("DEC_WM_HINTS", name))
    Dec_Wm_Hints = reply.atom;
  if (!strcmp ("DEC_WM_DECORATION_GEOMETRY", name))
    Dec_Wm_Decoration_Geometry = reply.atom;
  reply.type = X_Reply;
  reply.sequenceNumber = client->sequence;
  reply.length = 0;
  WriteToClient (client, sizeof (xInternAtomReply), (char *) &reply);
  Xfree (name);
  return (client->noClientException);
}

int
_ProcGetAtomName (client)
  ClientPtr client;
{
  register xResourceReq *req = (xResourceReq *) client->requestBuffer;
  xGetAtomNameReply reply;
  register int length;
  char *atom_name;

  GETDISPLAY (dpy, client);

  atom_name = XGetAtomName (dpy, req->id);

  /* ensure reply/event sequence */
  RESERIALIZE (dpy);

  if (atom_name != NULL) {
    length = strlen (atom_name);
    reply.type = X_Reply;
    reply.length = (length + 3) >> 2;
    reply.sequenceNumber = client->sequence;
    reply.nameLength = length;

    WriteToClient (client, sizeof (xGetAtomNameReply),
		   (char *) &reply);

    WriteToClient (client, length, atom_name);

    Xfree (atom_name);

    return (client->noClientException);
  }
  return (clientErrorValue ? clientErrorValue : BadAccess);
}

int
_ProcGetProperty (client)
  ClientPtr client;
{
  register xGetPropertyReq *req =
  (xGetPropertyReq *) client->requestBuffer;
  xGetPropertyReply reply;
  register XID win;
  Atom actual_type;
  int actual_format;
  unsigned long nitems, bytesafter;
  unsigned char *prop;

  GETDISPLAY (dpy, client);
  prop = (unsigned char *) NULL;
  MAPID (win, req->window, ConnectionNumber (dpy), FromClient);

  XGetWindowProperty (dpy, win, req->property, req->longOffset,
		      req->longLength, req->delete, req->type,
		      &actual_type, &actual_format,
		      &nitems, &bytesafter, (unsigned char **) &prop);

  /* ensure reply/event sequence */
  RESERIALIZE (dpy);

  /* Check "long" properties for resource ID's */
  if (actual_format == 32)
    PSBuildProperty (actual_type, prop, nitems,
		     ConnectionNumber (dpy), FromServer);
  reply.type = X_Reply;
  reply.sequenceNumber = client->sequence;
  reply.format = actual_format;
  reply.propertyType = actual_type;
  reply.nItems = nitems;
  reply.length = (((actual_format >> 3) * nitems) + 3) >> 2;
  reply.bytesAfter = bytesafter;

  WriteToClient (client, sizeof (xGetPropertyReply), &reply);
  if (reply.length != 0) {
    WriteToClient (client, nitems * (actual_format >> 3), prop);
    Xfree ((char *) prop);
  }
  return (client->noClientException);
}


int
_ProcListProperties (client)
  ClientPtr client;
{
  register xResourceReq *req = (xResourceReq *) client->requestBuffer;
  xListPropertiesReply reply;
  register XID window;
  int num_props;
  Atom *properties;

  GETDISPLAY (dpy, client);
  MAPID (window, req->id, ConnectionNumber (dpy), FromClient);

  properties = (Atom *) NULL;

  properties = XListProperties (dpy, window, &num_props);

  /* ensure reply/event sequence */
  RESERIALIZE (dpy);

  reply.type = X_Reply;
  reply.sequenceNumber = client->sequence;
  reply.nProperties = num_props;
  reply.length = num_props;

  WriteToClient (client, sizeof (xListPropertiesReply),
		 (char *) &reply);
  if (properties != (Atom *) NULL) {
    WriteToClient (client, sizeof (Atom) * num_props,
		   (char *) properties);
    Xfree ((char *) properties);
    return (client->noClientException);
  }
  else
    return (clientErrorValue ? clientErrorValue : BadAlloc);
}

int
_ProcGetSelectionOwner (client)
  ClientPtr client;
{
  register xResourceReq *req = (xResourceReq *) client->requestBuffer;
  xGetSelectionOwnerReply reply;
  register XID owner;
  register int idmap;

  GETDISPLAY (dpy, client);
  idmap = ConnectionNumber (dpy);

  owner = XGetSelectionOwner (dpy, req->id);

  /* ensure reply/event sequence */
  RESERIALIZE (dpy);

  reply.type = X_Reply;
  reply.sequenceNumber = client->sequence;
  reply.length = 0;
  reply.owner = MapID (owner,
		       ConnectionNumber (dpy), FromServer);

  WriteToClient (client, sizeof (xGetSelectionOwnerReply),
		 (char *) &reply);

  return (clientErrorValue ? clientErrorValue : client->noClientException);
}

int
_ProcGrabPointer (client)
  ClientPtr client;
{
  register xGrabPointerReq *req =
  (xGrabPointerReq *) client->requestBuffer;
  xGrabPointerReply reply;
  register XID grab_window, confine_to, cursor;
  register int idmap, status;

  GETDISPLAY (dpy, client);
  idmap = ConnectionNumber (dpy);

  cursor = None;
  grab_window = None;
  confine_to = None;

  if (req->cursor)
    MAPID (cursor, req->cursor, idmap, FromClient);
  if (req->grabWindow)
    MAPID (grab_window, req->grabWindow, idmap, FromClient);
  if (req->confineTo)
    MAPID (confine_to, req->confineTo, idmap, FromClient);

  status = XGrabPointer (dpy, grab_window, req->ownerEvents,
			 req->eventMask, req->pointerMode,
			 req->keyboardMode, confine_to, cursor,
			 req->time);

  /* ensure reply/event sequence */
  RESERIALIZE (dpy);

  reply.type = X_Reply;
  reply.sequenceNumber = client->sequence;
  reply.length = 0;
  reply.status = status;
  WriteToClient (client, sizeof (xGrabPointerReply), (char *) &reply);

  return (client->noClientException);
}

int
_ProcGrabKeyboard (client)
  ClientPtr client;
{
  register xGrabKeyboardReq *req =
  (xGrabKeyboardReq *) client->requestBuffer;
  xGrabKeyboardReply reply;
  register XID grab_window;
  register int status;

  GETDISPLAY (dpy, client);
  MAPID (grab_window, req->grabWindow, ConnectionNumber (dpy),
	 FromClient);


  status = XGrabKeyboard (dpy, grab_window, req->ownerEvents,
			  req->pointerMode, req->keyboardMode,
			  req->time);

  /* ensure reply/event sequence */
  RESERIALIZE (dpy);

  reply.type = X_Reply;
  reply.sequenceNumber = client->sequence;
  reply.length = 0;
  reply.status = status;

  WriteToClient (client, sizeof (xGrabKeyboardReply), (char *) &reply);

  return (client->noClientException);
}

int
_ProcQueryPointer (client)
  ClientPtr client;
{
  register xResourceReq *req = (xResourceReq *) client->requestBuffer;
  xQueryPointerReply reply;
  register XID win;
  XID root, child;
  unsigned int mask;
  register int idmap, same_screen;
  int root_x, root_y, win_x, win_y;

  GETDISPLAY (dpy, client);
  idmap = ConnectionNumber (dpy);

  MAPID (win, req->id, idmap, FromClient);

  same_screen = XQueryPointer (dpy, win, &root, &child,
			       &root_x, &root_y,
			       &win_x, &win_y, &mask);
  /* ensure reply/event sequence */
  RESERIALIZE (dpy);

  if (same_screen)
    reply.sameScreen = xTrue;
  else
    reply.sameScreen = xFalse;

  reply.root = MapID (root, idmap, FromServer);
  if (child)
    reply.child = MapID (child, idmap, FromServer);
  reply.rootX = root_x;
  reply.rootY = root_y;
  reply.winX = win_x;
  reply.winY = win_y;
  reply.mask = mask;

  reply.type = X_Reply;
  reply.length = 0;
  reply.sequenceNumber = client->sequence;

  WriteToClient (client, sizeof (xQueryPointerReply), (char *) &reply);
  return (client->noClientException);
}

int
_ProcGetMotionEvents (client)
  ClientPtr client;
{
  register xGetMotionEventsReq *req =
  (xGetMotionEventsReq *) client->requestBuffer;
  xGetMotionEventsReply reply;
  Window window;
  XTimeCoord *coords;
  int n_events;

  GETDISPLAY (dpy, client);
  MAPID (window, req->window, ConnectionNumber (dpy), FromClient);
  coords = XGetMotionEvents (dpy, window, req->start, req->stop,
			     &n_events);
  RESERIALIZE (dpy);

  reply.type = X_Reply;
  reply.sequenceNumber = client->sequence;
  reply.nEvents = n_events;
  reply.length = n_events << 1;
  WriteToClient (client, sizeof (xGetMotionEventsReply),
		 (char *) &reply);
  if (n_events)
    WriteToClient (client, sizeof (xTimecoord) * n_events,
		   (char *) coords);

  Xfree ((char *) coords);
  return (client->noClientException);
}

int
_ProcTranslateCoords (client)	/* 40 */
  ClientPtr client;
{
  register xTranslateCoordsReq *req =
  (xTranslateCoordsReq *) client->requestBuffer;
  xTranslateCoordsReply reply;
  register XID src_win, dest_win;
  XID child;
  register int idmap;
  int dest_x, dest_y;

  GETDISPLAY (dpy, client);
  idmap = ConnectionNumber (dpy);

  MAPID (src_win, req->srcWid, idmap, FromClient);
  MAPID (dest_win, req->dstWid, idmap, FromClient);

  reply.sameScreen = XTranslateCoordinates (dpy, src_win, dest_win,
					    req->srcX, req->srcY,
					    &dest_x, &dest_y, &child);

  /* ensure reply/event sequence */
  RESERIALIZE (dpy);

  reply.type = X_Reply;
  reply.sequenceNumber = client->sequence;
  reply.length = 0;

  if (child)
    if (dest_win == DefaultRootWindow (dpy)) {

      /*
       * it's another child of the root window; register it (in case
       * our client will use it later)
       */
      InsertID (child, child, idmap, FromServer);
      InsertID (child, child, idmap, FromClient);
      reply.child = child;
    }
    else
      /* XXX no ; ( see macro definition ) ! */
      MAPID (reply.child, child, idmap, FromServer)
	else
      reply.child = None;

  reply.dstX = dest_x;
  reply.dstY = dest_y;

  WriteToClient (client, sizeof (xTranslateCoordsReply), (char *) &reply);

  return (client->noClientException);
}

int
_ProcGetInputFocus (client)
  ClientPtr client;
{
  register xReq *req = (xReq *) client->requestBuffer;
  xGetInputFocusReply reply;
  int revert_to;
  Window focus;

  GETDISPLAY (dpy, client);

  XGetInputFocus (dpy, &focus, &revert_to);

  /* ensure reply/event sequence */
  RESERIALIZE (dpy);

  reply.type = X_Reply;
  reply.sequenceNumber = client->sequence;
  reply.length = 0;
  reply.revertTo = revert_to;
  reply.focus = MapID (focus, ConnectionNumber (dpy), FromServer);

  WriteToClient (client, sizeof (xGetInputFocusReply), &reply);

  return (client->noClientException);
}

int
_ProcQueryKeymap (client)
  ClientPtr client;
{
  register xReq *req = (xReq *) client->requestBuffer;
  xQueryKeymapReply reply;
  char map[32];
  GETDISPLAY (dpy, client);
  XQueryKeymap (dpy, map);
  RESERIALIZE (dpy);
  reply.type = X_Reply;
  reply.sequenceNumber = client->sequence;
  reply.length = 2;
  WriteToClient (client, sizeof (xQueryKeymapReply), (char *) &reply);
  WriteToClient (client, sizeof (map), map);
  return (client->noClientException);
}

int
_ProcQueryFont (client)
  ClientPtr client;
{
  register xResourceReq *req = (xResourceReq *) client->requestBuffer;
  xQueryFontReply reply;
  XFontStruct *font_info = (XFontStruct *) NULL;
  register XID fid;
  register int idmap;

  GETDISPLAY (dpy, client);
  idmap = ConnectionNumber (dpy);
  if ((fid = MapID (req->id, idmap, FromClient)) == req->id) {
    /* Font-id not valid, return with error */
    clientErrorValue = BadFont;
    clientErrorRequest = X_QueryFont;

    return (clientErrorValue);
  }

  font_info = XQueryFont (dpy, fid);

  /* ensure reply/event sequence */
  RESERIALIZE (dpy);

  /*
   * We have Xlib functions that cause some difficulties, especially
   * XLoadQueryFont; X splits it into XLoadFont and XQueryFont.  We get in
   * trouble, if the server can't open the specified font: the error packet
   * (BadName) after XOpenFont is NOT ignored by us, because we have
   * incremented our serial number (dpy->request) which doesn't match with
   * the serial number in the error packet (but it should!)
   * 
   * There would be two "direct" ways to solve this problem:
   * - do a "request lookahead" (is it a xQueryFontReq?): this wouldn't work,
   *   if we got this request in the next round trip
   * - store the last request (was it a xOpenFontReq?): this would work, but we
   *   would have to violate the X rule "don't manipulate the display
   *   structure!" by decrementing dpy->request
   * 
   * So we use an "indirect" way: if we receive the BadName error after
   * OpenFont, we will simulate XOpenQueryFont by sending a error packet
   * (BadFont) with "aligned" serials
   */

  if (font_info != (XFontStruct *) NULL) {
    int num_CharInfos, length, num_FontProps;

    num_FontProps = font_info->n_properties;
    if (font_info->min_byte1 == 0 && font_info->max_byte1 == 0)
      num_CharInfos = font_info->max_char_or_byte2 -
	font_info->min_char_or_byte2 + 1;
    else
      num_CharInfos = (font_info->max_byte1 - font_info->min_byte1 + 1) *
	(font_info->max_char_or_byte2 -
	 font_info->min_char_or_byte2 + 1);

    reply.length = (sizeof (xQueryFontReply) - sizeof (xGenericReply) +
		    num_FontProps * sizeof (xFontProp) +
		    num_CharInfos * sizeof (xCharInfo)) >> 2;

    reply.type = X_Reply;
    reply.sequenceNumber = client->sequence;
    reply.minBounds.leftSideBearing = font_info->min_bounds.lbearing;
    reply.minBounds.rightSideBearing = font_info->min_bounds.rbearing;
    reply.minBounds.characterWidth = font_info->min_bounds.width;
    reply.minBounds.ascent = font_info->min_bounds.ascent;
    reply.minBounds.descent = font_info->min_bounds.descent;
    reply.minBounds.attributes = font_info->min_bounds.attributes;

    reply.maxBounds.leftSideBearing = font_info->max_bounds.lbearing;
    reply.maxBounds.rightSideBearing = font_info->max_bounds.rbearing;
    reply.maxBounds.characterWidth = font_info->max_bounds.width;
    reply.maxBounds.ascent = font_info->max_bounds.ascent;
    reply.maxBounds.descent = font_info->max_bounds.descent;
    reply.maxBounds.attributes = font_info->max_bounds.attributes;

    reply.minCharOrByte2 = font_info->min_char_or_byte2;
    reply.maxCharOrByte2 = font_info->max_char_or_byte2;
    reply.minByte1 = font_info->min_byte1;
    reply.maxByte1 = font_info->max_byte1;
    reply.allCharsExist = font_info->all_chars_exist;
    reply.fontAscent = font_info->ascent;
    reply.fontDescent = font_info->descent;
    reply.defaultChar = font_info->default_char;
    reply.nFontProps = font_info->n_properties;
    reply.nCharInfos = num_CharInfos;
    reply.drawDirection = font_info->direction;

    WriteToClient (client, sizeof (xQueryFontReply), (char *) &reply);
    WriteToClient (client, num_FontProps * sizeof (xFontProp),
		   (char *) font_info->properties);
    WriteToClient (client, num_CharInfos * sizeof (xCharInfo),
		   (char *) font_info->per_char);

    /* free all stuff */
    Xfree ((char *) font_info->per_char);
    Xfree ((char *) font_info->properties);
    Xfree ((char *) font_info);

    return (client->noClientException);
  }
  else
    /* something wrong during XQueryLoadFont */
  if (clientErrorValue == BadName) {
    xError error;
    /*****************************************************************
	    error.type           = X_Error ;
	    error.errorCode      = BadName ;
	    error.sequenceNumber = client->sequence - 1 ;
	    error.resourceID     = req->id ;
	    error.majorCode      = X_OpenFont ;
	    error.minorCode      = 0 ;

	    WriteToClient( client , sizeof( xError ) , ( char * ) &error ) ;
     *****************************************************************/
    /* make sure that we send the right second error */
    clientErrorValue = BadFont;
    clientErrorRequest = X_QueryFont;

    return (clientErrorValue);
  }
  return (clientErrorValue ? clientErrorValue : BadAlloc);
}

int
_ProcQueryTextExtents (client)
  ClientPtr client;
{
  register xQueryTextExtentsReq *req =
  (xQueryTextExtentsReq *) client->requestBuffer;
  xQueryTextExtentsReply reply;
  register Font font;
  int length, ok, direction, font_ascent, font_descent;
  XCharStruct overall;

  GETDISPLAY (dpy, client);
  MAPID (font, req->fid, ConnectionNumber (dpy), FromClient);
  length = req->length - (sizeof (xQueryTextExtentsReq) >> 2);
  length = length << 1;
  if (req->oddLength) {
    if (length == 0)
      return (BadLength);
    length--;
  }
  ok = XQueryTextExtents (dpy, font, (char *) &req[1], length,
			  &direction, &font_ascent, &font_descent,
			  &overall);
  RESERIALIZE (dpy);
  if (ok) {
    reply.type = X_Reply;
    reply.sequenceNumber = client->sequence;
    reply.length = 0;
    reply.drawDirection = direction;
    reply.fontAscent = font_ascent;
    reply.fontDescent = font_descent;
    reply.overallAscent = overall.ascent;
    reply.overallDescent = overall.descent;
    reply.overallWidth = overall.width;
    reply.overallLeft = overall.lbearing;
    reply.overallRight = overall.rbearing;
    WriteToClient (client, sizeof (xQueryTextExtentsReply),
		   (char *) &reply);
    return (client->noClientException);
  }
  else
    return (BadAlloc);
}

int
_ProcListFonts (client)
  ClientPtr client;
{
  register xListFontsReq *req = (xListFontsReq *) client->requestBuffer;
  xListFontsReply reply;
  char *pattern;
  char **font_names;
  int count, length, i;

  GETDISPLAY (dpy, client);
  if ((pattern = (char *) Xmalloc (req->nbytes + 1)) == NULL) {
    ErrorF ("Out of memory!\n");
    return (BadAlloc);
  }
  bcopy ((char *) &req[1], pattern, req->nbytes);
  pattern[req->nbytes] = '\0';
  font_names = (char **) NULL;
  font_names = XListFonts (dpy, pattern, req->maxNames, &count);
  /* ensure reply/event sequence */
  RESERIALIZE (dpy);
  Xfree (pattern);
  if (font_names != (char **) NULL) {
    char *buffer, *bufptr;
    length = 0;
    for (i = 0; i < count; i++)
      length += strlen (font_names[i]);
    /* every "string" starts with a length byte ! */
    length += count;
    if ((buffer = (char *) Xmalloc (length)) == NULL) {
      ErrorF ("Out of memory!\n");
      return (BadAlloc);
    }

    for (i = 0, bufptr = buffer;
	 i < count;
	 bufptr += strlen (font_names[i]), i++
      ) {
      *bufptr++ = strlen (font_names[i]);
      bcopy (font_names[i], bufptr, strlen (font_names[i]));
    }

    reply.type = X_Reply;
    reply.sequenceNumber = client->sequence;
    reply.nFonts = count;

    /*
     * that's what makes a protocol consistent
     */
    reply.length = (length + 3) >> 2;

    WriteToClient (client, sizeof (xListFontsReply), (char *) &reply);

    /*
     * WriteToClient does long word alignment
     */
    WriteToClient (client, length, (char *) buffer);

    /* free all stuff */
    Xfree (buffer);
    for (i = 0; i < count; i++)
      Xfree (font_names[i]);
    Xfree (font_names);
    return (client->noClientException);
  }
  return (BadAlloc);
}

int
_ProcListFontsWithInfo (client)	/* 50 */
  ClientPtr client;
{
  register xListFontsWithInfoReq *req =
  (xListFontsWithInfoReq *) client->requestBuffer;
  xListFontsWithInfoReply reply;
  Display *dpy;
  char *pattern;
  char **font_names;
  XFontStruct *font_infos;
  int count, i;

  GETDISPLAY (dpy, client);
  if ((pattern = (char *) Xmalloc (req->nbytes + 1)) == NULL) {
    ErrorF ("Out of memory!\n");
    return (BadAlloc);
  }
  bcopy ((char *) &req[1], pattern, req->nbytes);
  pattern[req->nbytes] = '\0';
  font_names = (char **) NULL;
  font_names = XListFontsWithInfo (dpy, pattern, req->maxNames,
				   &count, &font_infos);
  /* ensure reply/event sequence */
  RESERIALIZE (dpy);
  /* free font pattern */
  Xfree (pattern);
  if ((font_names != (char **) NULL)) {
    int length, num_FontProps;
    char *name = *font_names;
    for (i = 0; i < count; i++) {
      num_FontProps = font_infos[i].n_properties;
      reply.nameLength = strlen (name);
      reply.length = (sizeof (xListFontsWithInfoReply)
		      - sizeof (xGenericReply) +
		      num_FontProps * sizeof (xFontProp) +
		      reply.nameLength + 3) >> 2;
      reply.type = X_Reply;
      reply.sequenceNumber = client->sequence;
      reply.minBounds.leftSideBearing =
	font_infos[i].min_bounds.lbearing;
      reply.minBounds.rightSideBearing =
	font_infos[i].min_bounds.rbearing;
      reply.minBounds.characterWidth =
	font_infos[i].min_bounds.width;
      reply.minBounds.ascent =
	font_infos[i].min_bounds.ascent;
      reply.minBounds.descent =
	font_infos[i].min_bounds.descent;
      reply.minBounds.attributes =
	font_infos[i].min_bounds.attributes;

      reply.maxBounds.leftSideBearing =
	font_infos[i].max_bounds.lbearing;
      reply.maxBounds.rightSideBearing =
	font_infos[i].max_bounds.rbearing;
      reply.maxBounds.characterWidth =
	font_infos[i].max_bounds.width;
      reply.maxBounds.ascent =
	font_infos[i].max_bounds.ascent;
      reply.maxBounds.descent =
	font_infos[i].max_bounds.descent;
      reply.maxBounds.attributes =
	font_infos[i].max_bounds.attributes;

      reply.minCharOrByte2 = font_infos[i].min_char_or_byte2;
      reply.maxCharOrByte2 = font_infos[i].max_char_or_byte2;
      reply.minByte1 = font_infos[i].min_byte1;
      reply.maxByte1 = font_infos[i].max_byte1;
      reply.allCharsExist = font_infos[i].all_chars_exist;
      reply.fontAscent = font_infos[i].ascent;
      reply.fontDescent = font_infos[i].descent;
      reply.defaultChar = font_infos[i].default_char;
      reply.nFontProps = font_infos[i].n_properties;
      reply.drawDirection = font_infos[i].direction;
      reply.nReplies = count - i;

      WriteToClient (client, sizeof (xListFontsWithInfoReply),
		     (char *) &reply);
      WriteToClient (client, num_FontProps * sizeof (xFontProp),
		     (char *) font_infos[i].properties);
      WriteToClient (client, reply.nameLength,
		     (char *) name);

      name += reply.nameLength;

      /* free font properties */
      Xfree ((char *) font_infos[i].properties);

    }
    /* last reply has other format */
    reply.type = X_Reply;
    reply.sequenceNumber = client->sequence;
    reply.nameLength = 0;
    reply.length = (sizeof (xListFontsWithInfoReply)
		    - sizeof (xGenericReply)) >> 2;
    WriteToClient (client, sizeof (xListFontsWithInfoReply),
		   (char *) &reply);

    /* free all stuff */
    Xfree ((char *) font_infos);
    for (i = 0; i < count; i++)
      Xfree (font_names[i]);
    Xfree (font_names);
    return (client->noClientException);
  }
  else
    return (clientErrorValue ? clientErrorValue : BadAlloc);
}

int
_ProcGetFontPath (client)
  ClientPtr client;
{
  register xReq *req = (xReq *) client->requestBuffer;
  xGetFontPathReply reply;
  char **paths = (char **) NULL;
  int n_paths;

  GETDISPLAY (dpy, client);
  paths = XGetFontPath (dpy, &n_paths);
  RESERIALIZE (dpy);
  if (paths != (char **) NULL) {
    char *buffer, *bufptr;
    int i, total, *length;

    if ((length = (int *) Xmalloc (n_paths * sizeof (int))) == NULL)
      return (BadAlloc);
    total = 0;
    for (i = 0; i < n_paths; i++) {
      length[i] = strlen (paths[i]);
      total += length[i];
    }
    reply.type = X_Reply;
    reply.sequenceNumber = client->sequence;
    /* each name starts with a length byte */
    reply.length = (total + n_paths + 3) >> 2;
    reply.nPaths = n_paths;

    bufptr = buffer = (char *) Xmalloc (reply.length << 2);
    if (!bufptr)
      return (BadAlloc);
    for (i = 0; i < n_paths; i++) {
      *bufptr++ = length[i];
      bcopy (paths[i], bufptr, length[i]);
      bufptr += length[i];
    }
    WriteToClient (client, sizeof (xGetFontPathReply),
		   (char *) &reply);
    if (total || n_paths)
      WriteToClient (client, total + n_paths, buffer);

    Xfree (buffer);
    for (i = 0; i < n_paths; i++)
      Xfree (paths[i]);
    Xfree (paths);
    Xfree ((char *) length);
    return (client->noClientException);
  }
  else
    return (BadAlloc);
}

#ifndef IMAGE_BUFSIZE
#define IMAGE_BUFSIZE 8192
#endif

int
_ProcGetImage (client)
  ClientPtr client;
{
  register xGetImageReq *req = (xGetImageReq *) client->requestBuffer;
  xGetImageReply reply;
  register XID drawable;
  XImage *image = (XImage *) NULL;
  register int width;

  GETDISPLAY (dpy, client);
  MAPID (drawable, req->drawable, ConnectionNumber (dpy), FromClient);

  image = XGetImage (dpy, drawable, req->x, req->y,
		     req->width, req->height, req->planeMask,
		     req->format);

  /* ensure reply/event sequence */
  RESERIALIZE (dpy);

  if (image != (XImage *) NULL) {
    /* width       = image->bytes_per_line ; */
    width = PSComputeWidth (req->format,
			    image->width,
			    image->depth,
			    req->planeMask);
    reply.type = X_Reply;
    reply.sequenceNumber = client->sequence;
    reply.length = (image->height * width + 3) >> 2;
    reply.depth = image->depth;

    /*
     * XXX this causes some trouble: the reply must contain a visual
     * ID, but we don't get any visual information back from XGetImage.
     * The only one we know is the default (hope for the best!)
     */
    reply.visual = MapID (DefaultVisual (dpy, DefaultScreen (dpy)),
			  ConnectionNumber (dpy), FromServer);

    WriteToClient (client, sizeof (xGetImageReply), (char *) &reply);

    /*
     * The image; WriteToClient does padding
     * By the way: do you remember XPutImage? There, every image scan line
     * contained pad bytes we had to strip off. Here, when we give an image
     * back, we're only adding pad bytes at the end !
     */
    WriteToClient (client, image->height * width, image->data);

    /* free all stuff */
    XDestroyImage (image);

    return (client->noClientException);
  }
  return (clientErrorValue ? clientErrorValue : BadAlloc);
}

#undef IMAGE_BUFSIZE

int
_ProcListInstalledColormaps (client)
  ClientPtr client;
{
  register xResourceReq *req =
  (xResourceReq *) client->requestBuffer;
  xListInstalledColormapsReply reply;
  Window window;
  Colormap *cmaps;
  int idmap, n_cmaps;

  GETDISPLAY (dpy, client);
  idmap = ConnectionNumber (dpy);
  MAPID (window, req->id, idmap, FromClient);
  cmaps = XListInstalledColormaps (dpy, window, &n_cmaps);
  RESERIALIZE (dpy);
  if (cmaps != (Colormap *) NULL) {
    register int i;

    for (i = 0; i < n_cmaps; i++)
      MAPID (cmaps[i], cmaps[i], idmap, FromServer);

    reply.type = X_Reply;
    reply.sequenceNumber = client->sequence;
    reply.length =
      reply.nColormaps = n_cmaps;
    WriteToClient (client, sizeof (xListInstalledColormapsReply),
		   (char *) &reply);
    WriteToClient (client, n_cmaps * sizeof (Colormap), cmaps);
    Xfree ((char *) cmaps);
    return (client->noClientException);
  }
  else
    return (BadAlloc);
}

int
_ProcAllocColor (client)
  ClientPtr client;
{
  register xAllocColorReq *req =
  (xAllocColorReq *) client->requestBuffer;
  xAllocColorReply reply;
  register XID cmap;
  register int ok;
  XColor color;

  GETDISPLAY (dpy, client);
  color.red = req->red;
  color.green = req->green;
  color.blue = req->blue;
  MAPID (cmap, req->cmap, ConnectionNumber (dpy), FromClient);

  ok = XAllocColor (dpy, cmap, &color);

  /* ensure reply/event sequence */
  RESERIALIZE (dpy);

  if (ok) {
    reply.type = X_Reply;
    reply.length = 0;
    reply.sequenceNumber = client->sequence;
    reply.red = color.red;
    reply.green = color.green;
    reply.blue = color.blue;
    reply.pixel = color.pixel;
    WriteToClient (client, sizeof (xAllocColorReply),
		   (char *) &reply);
    return (client->noClientException);
  }
  return (clientErrorValue ? clientErrorValue : BadAccess);
}

int
_ProcAllocNamedColor (client)	/* 85 */
  ClientPtr client;
{
  register xAllocNamedColorReq *req =
  (xAllocNamedColorReq *) client->requestBuffer;
  xAllocNamedColorReply reply;
  register XID cmap;
  XColor exact_def, hardw_def;
  register int ok;
  char *name = NULL;

  GETDISPLAY (dpy, client);
  MAPID (cmap, req->cmap, ConnectionNumber (dpy), FromClient);
  if ((name = (char *) Xmalloc (req->nbytes + 1)) == NULL) {
    ErrorF ("Out of memory!\n");
    return (BadAlloc);
  }
  bcopy ((char *) &req[1], name, req->nbytes);
  name[req->nbytes] = '\0';
  ok = XAllocNamedColor (dpy, cmap, name, &hardw_def, &exact_def);
  /* ensure reply/event sequence */
  RESERIALIZE (dpy);
  Xfree (name);
  if (ok) {
    reply.type = X_Reply;
    reply.length = 0;
    reply.sequenceNumber = client->sequence;
    reply.screenRed = hardw_def.red;
    reply.screenGreen = hardw_def.green;
    reply.screenBlue = hardw_def.blue;

    reply.exactRed = exact_def.red;
    reply.exactBlue = exact_def.blue;
    reply.exactGreen = exact_def.green;

    reply.pixel = hardw_def.pixel;

    WriteToClient (client, sizeof (xAllocNamedColorReply),
		   (char *) &reply);
    return (client->noClientException);
  }
  return (clientErrorValue ? clientErrorValue : BadName);
}

int
_ProcAllocColorCells (client)
  ClientPtr client;
{
  register xAllocColorCellsReq *req = (xAllocColorCellsReq *) client->requestBuffer;
  xAllocColorCellsReply reply;
  register int ok;
  register XID cmap;
  register int npixels;
  register int nplanes;
  unsigned long *planes = NULL, *pixels = NULL;

  npixels = req->colors;
  nplanes = req->planes;

  GETDISPLAY (dpy, client);
  MAPID (cmap, req->cmap, ConnectionNumber (dpy), FromClient);

  if (npixels > 0)
    if ((pixels =
	 (unsigned long *)
	 Xmalloc (npixels * sizeof (unsigned long))) == NULL)
      return (BadAlloc);
  if (nplanes > 0)
    if ((planes =
	 (unsigned long *)
	 Xmalloc (nplanes * sizeof (unsigned long))) == NULL)
      return (BadAlloc);
  ok = XAllocColorCells (dpy, cmap, req->contiguous,
			 planes, nplanes, pixels, npixels);

  /* ensure reply/event sequence */
  RESERIALIZE (dpy);
  if (ok) {
    reply.type = X_Reply;
    reply.length = npixels + nplanes;
    reply.sequenceNumber = client->sequence;
    reply.nPixels = npixels;
    reply.nMasks = nplanes;
    WriteToClient (client, sizeof (xAllocColorCellsReply),
		   (char *) &reply);
    if (npixels > 0) {
      WriteToClient (client, npixels * sizeof (unsigned long),
		     (char *) pixels);
      Xfree ((char *) pixels);
    }
    if (nplanes > 0) {
      WriteToClient (client, nplanes * sizeof (unsigned long),
		     (char *) planes);
      Xfree ((char *) planes);
    }
    return (client->noClientException);
  }
  return (clientErrorValue ? clientErrorValue : BadAlloc);
}

int
_ProcAllocColorPlanes (client)
  ClientPtr client;
{
  register xAllocColorPlanesReq *req =
  (xAllocColorPlanesReq *) client->requestBuffer;
  xAllocColorPlanesReply reply;
  Colormap colormap;
  int ok;
  unsigned long *pixels, red_mask, green_mask, blue_mask;

  GETDISPLAY (dpy, client);
  MAPID (colormap, req->cmap, ConnectionNumber (dpy), FromClient);
  if (req->colors) {
    pixels =
      (unsigned long *) Xmalloc (req->colors * sizeof (unsigned long));
    if (!pixels)
      return (BadAlloc);
  }
  ok = XAllocColorPlanes (dpy, colormap, req->contiguous,
			  pixels, req->colors,
			  req->red, req->green, req->blue,
			  &red_mask, &green_mask, &blue_mask);
  RESERIALIZE (dpy);
  if (ok) {
    reply.type = X_Reply;
    reply.sequenceNumber = client->sequence;
    reply.length = req->colors;
    reply.nPixels = req->colors;
    reply.redMask = red_mask;
    reply.greenMask = green_mask;
    reply.blueMask = blue_mask;
    WriteToClient (client, sizeof (xAllocColorPlanesReply),
		   (char *) &reply);
    if (req->colors) {
      WriteToClient (client, req->colors * sizeof (unsigned long),
		     (char *) &pixels);
      Xfree ((char *) pixels);
    }
    return (client->noClientException);
  }
  else
    return (clientErrorValue ? clientErrorValue : BadAlloc);
}

int
_ProcQueryColors (client)
  ClientPtr client;
{
  register xQueryColorsReq *req =
  (xQueryColorsReq *) client->requestBuffer;
  xQueryColorsReply reply;
  register XID cmap;
  XColor *colors;
  register int num_colors, i;
  xrgb *rgbs;


  GETDISPLAY (dpy, client);
  MAPID (cmap, req->cmap, ConnectionNumber (dpy), FromClient);
  num_colors = ((req->length << 2) - sizeof (xQueryColorsReq)) /
    sizeof (unsigned long);

  if ((colors = (XColor *) Xmalloc (num_colors * sizeof (XColor))) ==
      (XColor *) NULL) {
    ErrorF ("Can't allocate colors (Out of memory)!\n");
    return (BadAlloc);
  }
  if ((rgbs = (xrgb *) Xmalloc (num_colors * sizeof (xrgb))) ==
      (xrgb *) NULL) {
    ErrorF ("Can't allocate colors (Out of memory)!\n");
    return (BadAlloc);
  }
  PSBuildColors (ColPixel, &req[1], colors, num_colors);

  XQueryColors (dpy, cmap, colors, num_colors);

  /* ensure reply/event sequence */
  RESERIALIZE (dpy);

  reply.type = X_Reply;
  reply.length = num_colors << 1;
  reply.sequenceNumber = client->sequence;
  reply.nColors = num_colors;

  WriteToClient (client, sizeof (xQueryColorsReply), (char *) &reply);
  for (i = 0; i < num_colors; i++) {
    rgbs[i].red = colors[i].red;
    rgbs[i].green = colors[i].green;
    rgbs[i].blue = colors[i].blue;
  }
  WriteToClient (client, num_colors * sizeof (xrgb), (char *) rgbs);
  /* free all stuff */
  Xfree ((char *) colors);
  Xfree ((char *) rgbs);

  return (client->noClientException);
}

int
_ProcLookupColor (client)
  ClientPtr client;
{
  register xLookupColorReq *req =
  (xLookupColorReq *) client->requestBuffer;
  xLookupColorReply reply;
  register int ok;
  XID cmap;
  char *name;
  XColor visual_def, exact_def;

  GETDISPLAY (dpy, client);
  MAPID (cmap, req->cmap, ConnectionNumber (dpy), FromClient);
  if ((name = (char *) Xmalloc (req->nbytes + 1)) == NULL) {
    ErrorF ("Out of memory!\n");
    return (BadAlloc);
  }
  bcopy ((char *) &req[1], name, req->nbytes);
  name[req->nbytes] = '\0';
  ok = XLookupColor (dpy, cmap, name, &visual_def, &exact_def);
  /* ensure reply/event sequence */
  RESERIALIZE (dpy);
  Xfree (name);
  if (ok) {
    reply.type = X_Reply;
    reply.sequenceNumber = client->sequence;
    reply.length = 0;

    reply.exactRed = exact_def.red;
    reply.exactGreen = exact_def.green;
    reply.exactBlue = exact_def.blue;

    reply.screenRed = visual_def.red;
    reply.screenGreen = visual_def.green;
    reply.screenBlue = visual_def.blue;

    WriteToClient (client, sizeof (xLookupColorReply), (char *) &reply);

    return (client->noClientException);
  }
  return (clientErrorValue ? clientErrorValue : BadName);
}

int
_ProcQueryBestSize (client)
  ClientPtr client;
{
  register xQueryBestSizeReq *req =
  (xQueryBestSizeReq *) client->requestBuffer;
  xQueryBestSizeReply reply;
  register XID drawable;
  register int ok;
  unsigned int width, height;

  GETDISPLAY (dpy, client);
  MAPID (drawable, req->drawable, ConnectionNumber (dpy), FromClient);

  ok = XQueryBestSize (dpy, req->class, drawable, req->width,
		       req->height, &width, &height);

  /* ensure reply/event sequence */
  RESERIALIZE (dpy);

  if (ok) {
    reply.type = X_Reply;
    reply.sequenceNumber = client->sequence;
    reply.length = 0;
    reply.width = width;
    reply.height = height;

    WriteToClient (client, sizeof (xQueryBestSizeReply),
		   (char *) &reply);

    return (client->noClientException);
  }
  return (clientErrorValue ? clientErrorValue : BadValue);
}

int
_ProcQueryExtension (client)
  ClientPtr client;
{
  register xQueryExtensionReq *req =
  (xQueryExtensionReq *) client->requestBuffer;
  xQueryExtensionReply reply;
  char *name;
  int major_opcode, first_event, first_error;

  GETDISPLAY (dpy, client);
  if ((name = (char *) Xmalloc (req->nbytes + 1)) == NULL)
    return (BadAlloc);
  bcopy ((char *) &req[1], name, req->nbytes);
  name[req->nbytes] = '\0';
  reply.type = X_Reply;
  reply.sequenceNumber = client->sequence;
  reply.length = 0;
  if (XQueryExtension (dpy, name, &major_opcode, &first_event,
		       &first_error)) {
    reply.present = xTrue;
    reply.major_opcode = major_opcode;
    reply.first_event = first_event;
    reply.first_error = first_error;
  }
  else {
    reply.present = xFalse;
    reply.major_opcode = major_opcode;
    reply.first_event = first_event;
    reply.first_error = first_error;
  }
  Xfree (name);
  RESERIALIZE (dpy);
  WriteToClient (client, sizeof (xQueryExtensionReply),
		 (char *) &reply);
  return (client->noClientException);
}

int
_ProcListExtensions (client)
  ClientPtr client;
{
  register xReq *req = (xReq *) client->requestBuffer;
  xListExtensionsReply reply;
  char **list;
  char *buffer, *bufptr;
  int n_extensions, *length, i, total;

  reply.type = X_Reply;
  reply.sequenceNumber = client->sequence;

#ifdef SUPPORT_EXTENSIONS
  GETDISPLAY (dpy, client);
  list = XListExtensions (dpy, &n_extensions);
  RESERIALIZE (dpy);

  if (n_extensions) {
    if ((length =
	 (int *) Xmalloc (n_extensions * sizeof (int))) == NULL)
      return (BadAlloc);

    total = 0;
    for (i = 0; i < n_extensions; i++) {
      length[i] = strlen (list[i]);
      total += length[i];
    }
    reply.nExtensions = n_extensions;
    reply.length = (n_extensions + total + 3) >> 2;
    bufptr = buffer = (char *) Xmalloc (reply.length << 2);
    if (!bufptr)
      return (BadAlloc);
    for (i = 0; i < n_extensions; i++) {
      *bufptr++ = length[i];
      bcopy (list[i], bufptr, length[i]);
      bufptr += length[i];
    }
    WriteToClient (client, sizeof (xListExtensionsReply),
		   (char *) &reply);
    WriteToClient (client, reply.length << 2, buffer);
    for (i = 0; i < n_extensions; i++)
      Xfree (list[i]);
    Xfree ((char *) length);
    Xfree (list);
    Xfree (buffer);
  }
  else {
    reply.length = 0;
    WriteToClient (client, sizeof (xListExtensionsReply),
		   (char *) &reply);
  }
#else
  reply.length = 0;
  WriteToClient (client, sizeof (xListExtensionsReply),
		 (char *) &reply);
#endif
  return (client->noClientException);
}

int
_ProcGetKeyboardMapping (client)
  ClientPtr client;
{
  register xGetKeyboardMappingReq *req =
  (xGetKeyboardMappingReq *) client->requestBuffer;
  xGetKeyboardMappingReply reply;

  KeySym *keysyms;
  int length, keysyms_per_keycode;

  GETDISPLAY (dpy, client);

  keysyms = XGetKeyboardMapping (dpy, req->firstKeyCode, req->count,
				 &keysyms_per_keycode);

  /* ensure reply/event sequence */
  RESERIALIZE (dpy);

  if (keysyms != (KeySym *) NULL) {
    reply.type = X_Reply;
    reply.sequenceNumber = client->sequence;

    reply.keySymsPerKeyCode = keysyms_per_keycode;

    /*
     * length is a count of 4 byte quantities and KeySyms are 4 bytes
     */
    reply.length =
      length = req->count * keysyms_per_keycode;
    WriteToClient (client, sizeof (xGetKeyboardMappingReply),
		   (char *) &reply);
    WriteToClient (client, length * sizeof (KeySym),
		   (char *) keysyms);

    Xfree ((char *) keysyms);

    return (client->noClientException);
  }
  return (clientErrorValue ? clientErrorValue : BadAccess);
}

int
_ProcGetKeyboardControl (client)
  ClientPtr client;
{
  register xReq *req = (xReq *) client->requestBuffer;
  xGetKeyboardControlReply reply;
  XKeyboardState state;

  GETDISPLAY (dpy, client);
  XGetKeyboardControl (dpy, &state);
  RESERIALIZE (dpy);
  reply.type = X_Reply;
  reply.sequenceNumber = client->sequence;
  reply.length = 5;
  reply.globalAutoRepeat = state.global_auto_repeat;
  reply.bellPercent = state.bell_percent;
  reply.bellPitch = state.bell_pitch;
  reply.bellDuration = state.bell_duration;
  reply.ledMask = state.led_mask;
  bcopy ((char *) state.auto_repeats, (char *) reply.map, 32);
  WriteToClient (client, sizeof (xGetKeyboardControlReply),
		 (char *) &reply);
  return (client->noClientException);
}

int
_ProcGetPointerControl (client)
  ClientPtr client;
{
  register xReq *req = (xReq *) client->requestBuffer;
  xGetPointerControlReply reply;
  int acc_num, acc_denom, thresh;
  GETDISPLAY (dpy, client);
  XGetPointerControl (dpy, &acc_num, &acc_denom, &thresh);
  RESERIALIZE (dpy);
  reply.type = X_Reply;
  reply.sequenceNumber = client->sequence;
  reply.length = 0;
  reply.accelNumerator = acc_num;
  reply.accelDenominator = acc_denom;
  reply.threshold = thresh;
  WriteToClient (client, sizeof (xGetPointerControlReply),
		 (char *) &reply);
  return (client->noClientException);
}

int
_ProcGetScreenSaver (client)
  ClientPtr client;
{
  register xReq *req = (xReq *) client->requestBuffer;
  xGetScreenSaverReply reply;
  int timeout, interval, prefer_blanking, allow_exposures;
  GETDISPLAY (dpy, client);
  XGetScreenSaver (dpy, &timeout, &interval, &prefer_blanking,
		   &allow_exposures);
  RESERIALIZE (dpy);
  reply.type = X_Reply;
  reply.sequenceNumber = client->sequence;
  reply.length = 0;
  reply.timeout = timeout;
  reply.interval = interval;
  reply.preferBlanking = prefer_blanking;
  reply.allowExposures = allow_exposures;
  WriteToClient (client, sizeof (xGetScreenSaverReply),
		 (char *) &reply);
  return (client->noClientException);
}

int
_ProcListHosts (client)		/* 110 */
  ClientPtr client;
{
  register xReq *req = (xReq *) client->requestBuffer;
  xListHostsReply reply;
  Bool state;
  int n_hosts;
  XHostAddress *hosts;
  GETDISPLAY (dpy, client);
  hosts = XListHosts (dpy, &n_hosts, &state);
  RESERIALIZE (dpy);

  reply.type = X_Reply;
  reply.sequenceNumber = client->sequence;
  reply.length = n_hosts >> 2;
  reply.nHosts = n_hosts;
  reply.enabled = state;
  WriteToClient (client, sizeof (xListHostsReply), (char *) &reply);

  if (hosts) {
    int i;

    for (i = 0; i < n_hosts; i++)
      WriteToClient (client, hosts[i].length + sizeof (XHostAddress),
		     (char *) &hosts[i]);
    Xfree ((char *) hosts);
  }
  return (client->noClientException);
}

int
_ProcSetPointerMapping (client)
  ClientPtr client;
{
  register xSetPointerMappingReq *req =
  (xSetPointerMappingReq *) client->requestBuffer;
  xSetPointerMappingReply reply;

  GETDISPLAY (dpy, client);
  reply.type = X_Reply;
  reply.sequenceNumber = client->sequence;
  reply.length = 0;
  reply.success = XSetPointerMapping (dpy, (unsigned char *) &req[1],
				      req->nElts);
  RESERIALIZE (dpy);
  WriteToClient (client, sizeof (xSetPointerMappingReply),
		 (char *) &reply);
  return (client->noClientException);
}

#define MAX_MAPPING 1000

int
_ProcGetPointerMapping (client)
  ClientPtr client;
{
  register xReq *req = (xReq *) client->requestBuffer;
  xGetPointerMappingReply reply;
  unsigned char map[MAX_MAPPING];
  int n_map, returned;

  GETDISPLAY (dpy, client);
  /* this should be REALLY big */
  n_map = MAX_MAPPING;
  returned = XGetPointerMapping (dpy, map, n_map);
  RESERIALIZE (dpy);
  reply.type = X_Reply;
  reply.sequenceNumber = client->sequence;
  reply.nElts = returned;
  reply.length = (returned + 3) >> 2;
  WriteToClient (client, sizeof (xGetPointerMappingReply),
		 (char *) &reply);
  WriteToClient (client, returned, map);
  return (client->noClientException);
}

#undef MAX_MAPPING

int
_ProcSetModifierMapping (client)
  ClientPtr client;
{
  register xSetModifierMappingReq *req =
  (xSetModifierMappingReq *) client->requestBuffer;
  xSetModifierMappingReply reply;
  XModifierKeymap modifier_map;
  register int success;

  GETDISPLAY (dpy, client);
  modifier_map.max_keypermod = req->numKeyPerModifier;
  if ((modifier_map.modifiermap = (KeyCode *)
       Xmalloc (8 * req->numKeyPerModifier * sizeof (KeyCode)))
      == (KeyCode *) NULL) {
    ErrorF ("Out of memory!\n");
    return (BadAlloc);
  }
  bcopy ((char *) &req[1], modifier_map.modifiermap,
	 8 * req->numKeyPerModifier * sizeof (KeyCode));
  success = XSetModifierMapping (dpy, &modifier_map);
  /* ensure reply/event sequence */
  RESERIALIZE (dpy);
  Xfree ((char *) modifier_map.modifiermap);

  reply.type = X_Reply;
  reply.sequenceNumber = client->sequence;
  reply.length = 0;
  reply.success = success;

  WriteToClient (client, sizeof (xSetModifierMappingReply),
		 (char *) &reply);

  return (client->noClientException);
}

int
_ProcGetModifierMapping (client)
  ClientPtr client;
{
  register xReq *req = (xReq *) client->requestBuffer;
  xGetModifierMappingReply reply;

  XModifierKeymap *modifier;

  GETDISPLAY (dpy, client);

  modifier = XGetModifierMapping (dpy);

  /* ensure reply/event sequence */
  RESERIALIZE (dpy);

  if (modifier != (XModifierKeymap *) NULL) {
    reply.type = X_Reply;
    reply.sequenceNumber = client->sequence;
    reply.numKeyPerModifier = modifier->max_keypermod;

    /*
     * length counts 4 byte quantities - there are 8 modifiers 1 byte
     * big
     */
    reply.length = 2 * modifier->max_keypermod;

    WriteToClient (client, sizeof (xGetModifierMappingReply),
		   (char *) &reply);
    WriteToClient (client, 8 * modifier->max_keypermod,
		   (char *) modifier->modifiermap);

    /* free al stuff */
    Xfree ((char *) modifier->modifiermap);
    Xfree ((char *) modifier);
    return (client->noClientException);
  }
  return (clientErrorValue ? clientErrorValue : BadAccess);
}
